C#
ASP.NET
ASP.NET_MVC

ASP.NET Razor ページで Web Form の User Control (ascx) を描画する方法とその逆の方法

ASP.NET の Web Form と MVC (Razor) が共存している環境で、あるパーツはどちらかで書いて共通して使いたい場合のやり方。
ググれば出てくるんですが検索ワードを忘れがちなのでまとめ。

引用元

(Web Form in Razor Page) https://stackoverflow.com/questions/7934319/use-a-legacy-asp-net-ascx-user-control-in-mvc-razor-view
(Razor Page in Web Form) https://stackoverflow.com/questions/702746/how-to-include-a-partial-view-inside-a-webform

Web Form in Razor Page

User Control の継承元を System.Web.UI.UserControl から System.Web.Mvc.ViewUserControl に変更する。

public partial class WebUserControl1 : UserControl
{
    // ...
}
// 上を下に
public partial class WebUserControl1 : ViewUserControl
{
    // ...
}

描画方法は下記の通り。

@Html.Partial("~/UserControls/WebUserControl1.ascx")

モデルを渡す場合

public partial class WebUserControl1 : ViewUserControl<dynamic>
{
    public string Hoge { get; set; }

    protected void Page_Load(object sender, EventArgs e)
    {
        Hoge = base.Model;
    }
}
@Html.Partial("~/UserControls/WebUserControl1.ascx", "テスト")

dynamicは適宜好きなクラスに置き換えてください。

Razor Page in Web Form

ダミーコントローラーと描画用のユーティリティメソッドを使って描画。

public class WebFormController : Controller { }

public static class WebFormMVCUtil
{

    public static void RenderPartial( string partialName, object model )
    {
        //get a wrapper for the legacy WebForm context
        var httpCtx = new HttpContextWrapper( System.Web.HttpContext.Current );

        //create a mock route that points to the empty controller
        var rt = new RouteData();
        rt.Values.Add( "controller", "WebFormController" );

        //create a controller context for the route and http context
        var ctx = new ControllerContext( 
            new RequestContext( httpCtx, rt ), new WebFormController() );

        //find the partial view using the viewengine
        var view = ViewEngines.Engines.FindPartialView( ctx, partialName ).View;

        //create a view context and assign the model
        var vctx = new ViewContext( ctx, view, 
            new ViewDataDictionary { Model = model }, 
            new TempDataDictionary() );

        //render the partial view
        view.Render( vctx, System.Web.HttpContext.Current.Response.Output );
    }
}
<% WebFormMVCUtil.RenderPartial( "ViewName", this.GetModel() ); %>