33

PartialView を HTML 文字列にレンダリングして、SignalR ajax 要求に返すことができるようにしたいと考えています。

何かのようなもの:

SignalR ハブ(mySignalHub.cs)

public class mySignalRHub: Hub
{
    public string getTableHTML()
    {
        return PartialView("_MyTablePartialView", GetDataItems()) // *How is it possible to do this*
    }
}

Razor PartialView (_MyTablePartialView.cshtml)

@model IEnumerable<DataItem>

<table>
    <tbody>
        @foreach (var dataItem in Model)
        {
        <tr>
            <td>@dataItem.Value1</td>
            <td>@dataItem.Value2</td>
        </tr>
        }
    </tbody>
</table>

HTML (MySignalRWebPage.html)

<Script>
    ...      
    //Get HTML from SignalR function call
    var tableHtml = $.connection.mySignalRHub.getTableHTML();

    //Inject into div
    $('#tableContainer).html(tableHtml);
</Script>

<div id="tableContainer"></div>

私の問題は、Controller の外で PartialView をレンダリングできないように見えることです。Controller の外で PartialView をレンダリングすることさえ可能ですか? Razor に付属している素晴らしい HTML 生成機能を引き続き活用できることは非常に素晴らしいことです。

私はこれについてすべて間違っていますか?別の方法はありますか?

4

6 に答える 6

14

ここで、これは私が ajax のコントローラーで使用するものです。コントローラーの代わりにメソッドから呼び出すことができるように少し変更しました。メソッドreturnViewはビューをレンダリングし、HTML 文字列を返すので、JS/jQuery を使用してページに挿入できます。クライアント側で受け取ります:

  public static string RenderPartialToString(string view, object model, ControllerContext Context)
        {
            if (string.IsNullOrEmpty(view))
            {
                view = Context.RouteData.GetRequiredString("action");
            }

            ViewDataDictionary ViewData = new ViewDataDictionary();

            TempDataDictionary TempData = new TempDataDictionary();

            ViewData.Model = model;

            using (StringWriter sw = new StringWriter())
            {
                ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(Context, view);

                ViewContext viewContext = new ViewContext(Context, viewResult.View, ViewData, TempData, sw);

                viewResult.View.Render(viewContext, sw);

                return sw.GetStringBuilder().ToString();
            }
        }

        //"Error" should be name of the partial view, I was just testing with partial error view
        //You can put whichever controller you want instead of HomeController it will be the same
        //You can pass model instead of null
        private string returnView()
        {
            var controller = new HomeController();
            controller.ControllerContext = new ControllerContext(HttpContext,new System.Web.Routing.RouteData(), controller);
            return RenderPartialToString("Error", null, new ControllerContext(controller.Request.RequestContext, controller));
        }

ハブではテストしていませんが、動作するはずです。

于 2012-07-30T12:17:42.110 に答える
6

Wimが示唆しているように、おそらく最良の選択はRazorEngineを使用することです。

public class mySignalRHub: Hub
{
    public string getTableHTML()
    {
        var viewModel = new[] { new DataItem { Value1 = "v1", Value2 = "v2" } };

        var template = File.ReadAllText(Path.Combine(
            AppDomain.CurrentDomain.BaseDirectory,
            @"Views\PathToTablePartialView\_MyTablePartialView.cshtml"));

        return Engine.Razor.RunCompile(template, "templateKey", null, viewModel);
    }
}
于 2012-07-30T13:02:49.780 に答える
4

上記の@ user1010609によって提供された回答に加えて、私もこれに苦労し、コントローラー名、ビューおよびモデルへのパスを指定して、レンダリングされた PartialView を返す関数になりました。

コントローラーがないため、SignalR イベントからの通常の状態ではないという事実を考慮します。

public static string RenderPartialView(string controllerName, string partialView, object model)
{
    var context = new HttpContextWrapper(System.Web.HttpContext.Current) as HttpContextBase;

    var routes = new System.Web.Routing.RouteData();
    routes.Values.Add("controller", controllerName);

    var requestContext = new RequestContext(context, routes);

    string requiredString = requestContext.RouteData.GetRequiredString("controller");
    var controllerFactory = ControllerBuilder.Current.GetControllerFactory();
    var controller = controllerFactory.CreateController(requestContext, requiredString) as ControllerBase;

    controller.ControllerContext = new ControllerContext(context, routes, controller);      

    var ViewData = new ViewDataDictionary();

    var TempData = new TempDataDictionary();

    ViewData.Model = model;

    using (var sw = new StringWriter())
    {
        var viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext, partialView);
        var viewContext = new ViewContext(controller.ControllerContext, viewResult.View, ViewData, TempData, sw);

        viewResult.View.Render(viewContext, sw);
        return sw.GetStringBuilder().ToString();
    }
}

次のようなもので呼び出します。

RenderPartialView("MyController", "~/Views/MyController/_partialView.cshtml", model);
于 2012-12-09T21:13:08.040 に答える
1

http://razorengine.codeplex.com/のようなカミソリ テンプレート エンジンの使用を考えたことはありますか? これを使用して部分ビューを解析することはできませんが、部分ビューとほぼ同様のカミソリ テンプレートを解析するために使用できます。

于 2012-07-30T11:45:27.293 に答える
0

RazorEngineHostとを使用するのはどうですかRazorTemplateEngine。あなたが探しているものかもしれないこの素敵な記事を見つけました。それは、ASP.NET (MVC) の外部で Razor をホストすることです。

于 2012-07-31T13:59:12.393 に答える
-1

以下の同様の質問に対する回答に基づいて、使用することをお勧めします

Html.Partial( partialViewName )

これは、SignalR 応答のコンテンツとして使用できるはずの MvcHtmlString を返します。ただし、これはテストしていません。

スタック オーバーフローの質問:コントローラーの外部でビューをレンダリングすることは可能ですか?

于 2012-07-26T07:22:26.433 に答える