简体   繁体   English

将MVC PartialView渲染为SignalR响应

[英]Render MVC PartialView into SignalR response

I would like to render a PartialView to an HTML string so I can return it to a SignalR ajax request. 我想将PartialView呈现为HTML字符串,以便将其返回到SignalR ajax请求。

Something like: 就像是:

SignalR Hub (mySignalHub.cs) SignalR Hub (mySignalHub.cs)

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

Razor PartialView (_MyTablePartialView.cshtml) 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) 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>

My problem is that I can't seem to render a PartialView outside of a Controller. 我的问题是我似乎无法在Controller之外渲染PartialView。 Is it even possible to render a PartialView outside of a Controller? 甚至可以在Controller外部渲染PartialView吗? It would be very nice to still be able to leverage the awesome HTML generating abilities that come with Razor. 能够利用Razor附带的令人敬畏的HTML生成能力将是非常好的。

Am I going about this all wrong? 我错了吗? Is there another way? 还有另外一种方法吗?

Here, this is what I use in Controllers for ajax, I modified it a bit so it can be called from method instead of controller, method returnView renders your view and returns HTML string so you can insert it with JS/jQuery into your page when you recive it on client side: 这里,这是我在控制器中使用的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));
        }

I didn't test it on a Hub but it should work. 我没有在Hub上测试它,但它应该工作。

Probably the best choice is to use RazorEngine , as Wim is suggesting. 可能最好的选择是使用RazorEngine ,正如Wim所暗示的那样。

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);
    }
}

Further to the answer provided by @user1010609 above, I struggled through this as well and have ended up with a function that returns the rendered PartialView given a controller name, path to the view and model. 除了上面@ user1010609提供的答案之外,我也在努力解决这个问题,并且最终得到了一个函数,该函数返回渲染的PartialView给定控制器名称,视图和模型的路径。

Takes account of the fact you don't have a controller and hence none of the usual state as coming from a SignalR event. 考虑到你没有控制器这一事实,因此没有一个通常的状态来自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();
    }
}

You would call it with something similar to: 你会用类似的东西来称呼它:

RenderPartialView("MyController", "~/Views/MyController/_partialView.cshtml", model);

Have you thought about using a razor template engine like http://razorengine.codeplex.com/ ? 你有没有想过使用像http://razorengine.codeplex.com/这样的剃须刀模板引擎? You can't use it to parse partial views but you can use it to parse razor templates, which are almost similar to partial views. 您不能使用它来解析部分视图,但您可以使用它来解析剃刀模板,这几乎与部分视图类似。

How about using the RazorEngineHost and RazorTemplateEngine . 如何使用RazorEngineHostRazorTemplateEngine I found this nice article that might be what you're looking for. 我发现这篇很好的文章可能就是你要找的东西。 It's about hosting Razor outside of ASP.NET (MVC). 它是关于在ASP.NET(MVC)之外托管Razor。

Based on the answers supplied to asimilar question below, I would suggest using 基于下面提供的相似问题的答案,我建议使用

Html.Partial( partialViewName ) Html.Partial( partialViewName

It returns an MvcHtmlString, which you should able to use as the content of your SignalR reponse. 它返回一个MvcHtmlString,您应该将其用作SignalR响应的内容。 I have not tested this, however. 但是,我没有测试过这个。

Stack Overflow Question: Is it possible to render a view outside a controller? 堆栈溢出问题: 是否可以在控制器外渲染视图?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM