Rendre MVC PartialView en réponse SignalR

j'aimerais rendre une vue partielle à une chaîne HTML pour que je puisse la retourner à une requête ajax SignalR.

quelque chose comme:

signal Hub (mySignalHub.cs)

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

Razor PartialView (_mytable Partialview.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>

Mon problème est que je ne peux pas rendre une vue partielle en dehors d'un Controller. Est-il même possible de rendre PartialView à l'extérieur d'un contrôleur? Il serait très agréable d'être encore en mesure de tirer parti des capacités géniales de génération HTML qui viennent avec Razor.

est-ce que je me trompe? Est-il une autre voie?

33
demandé sur Paolo Moretti 2012-07-25 08:37:31

6 réponses

ici, c'est ce que j'utilise dans les Controllers pour ajax, Je l'ai modifié un peu pour qu'il puisse être appelé de la méthode au lieu du controller, la méthode returnView rend votre vue et renvoie la chaîne HTML pour que vous puissiez l'insérer avec JS/jQuery dans votre page lorsque vous la Recevez du côté client:

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

Je ne l'ai pas testé sur un moyeu mais ça devrait marcher.

12
répondu formatc 2012-07-30 12:28:23

probablement le meilleur choix est d'utiliser RazorEngine , comme Wim suggère.

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);
    }
}
5
répondu Paolo Moretti 2017-05-23 12:10:21

suite à la réponse fournie par @user1010609 ci-dessus, j'ai lutté à travers cela aussi et j'ai fini avec une fonction qui retourne la vue partielle rendue en donnant un nom de contrôleur, un chemin vers la vue et le modèle.

Prend en compte le fait que vous n'avez pas de contrôleur et donc aucun état habituel d'une SignalR événement.

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

vous l'appelleriez avec quelque chose de similaire à:

RenderPartialView("MyController", "~/Views/MyController/_partialView.cshtml", model);
3
répondu JohnBarton 2012-12-09 21:13:08

avez-vous pensé à utiliser un moteur de modèle de rasoir comme http://razorengine.codeplex.com / ? Vous ne pouvez pas l'utiliser pour analyser des vues partielles, mais vous pouvez l'utiliser pour analyser les modèles de rasoir, qui sont presque semblables à des vues partielles.

1
répondu Wim 2012-07-30 11:45:27

Que Diriez-vous d'utiliser le RazorEngineHost et RazorTemplateEngine . J'ai trouvé cette bel article qui pourrait être ce que vous cherchez. Il s'agit d'accueillir Razor à l'extérieur de ASP.NET (MVC).

0
répondu Tx3 2012-07-31 13:59:12

basé sur les réponses fournies à une question similaire ci-dessous, je suggérerais d'utiliser

Html.Partial ( partialViewName )

renvoie une chaîne Mvchtml, que vous devriez pouvoir utiliser comme contenu de votre réponse SignalR. Je n'ai pas testé, cependant.

Stack Overflow Question: est-il possible de rendre une vue à l'extérieur d'un contrôleur?

-1
répondu Jason 2017-05-23 12:17:35