Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to call the Razor Compiler Programmatically from a Controller method?

I am using ASP .NET MVC 3 and I have an interesting problem to solve that I am hoping for some advice on.

I have a page that has a number of divs inside it. The contents of each div changes over time and so currently I have a timer for each div running that makes a $.ajax request to the server which returns a PartialViewResult with the updated contents of the div. The partial view is quite complex and references other views.

The problem with this approach is that it does not scale very well. It could be that each user has a lot of these timers running and with a lot of users the server is constantly being hit. I would rather, therefore, make a single request to the server that returns, potentially, multiple div contents so it would be:

div1 { some html }
div2 { some html }

...

Then on the client I could put each bit of HTML into the correct position on the page.

I thought that what I could do is return JSON from the server but my problem is - how do I get the HTML? At the moment the razor compiler will run and turn my partial view cshtml files into HTML but if I am returning JSON, is it possible to programmatically call the razor compiler?

I found Razor Engine here: http://razorengine.codeplex.com/ that seems to do what I want but is it possible to do it with just vanilla ASP NET MVC?

Or, given the problem, is there a better way that I could achieve my goal?

Thanks for any help!

like image 768
kmp Avatar asked Dec 20 '11 14:12

kmp


3 Answers

Create an Action that returns a new PartialView that renders all of those PartialViews. e.g. an action:

public PartialViewResult AggregatedAction(args)
{
    return PartialView();
}

with a view that contains:

@Html.Action("IndividualAction1", null)
@Html.Action("IndividualAction2", null)
@Html.Action("IndividualAction3", null)

See http://haacked.com/archive/2009/11/18/aspnetmvc2-render-action.aspx for more details.

That way there is only one request and the rendering engine is being called from the right place, i.e. the view.

Then with the result, you can search for the various divs and replace the html in the client.

$('div#id1').html('div#id1',$(data));
$('div#id2').html('div#id2',$(data));

If the structure of your page allows it, you should use: http://api.jquery.com/load/ (as @Jorge says) to replace all of the html with one line.

$('div#targetDiv').load('Controller\AggregatedAction', anyData);
like image 59
StuperUser Avatar answered Sep 19 '22 14:09

StuperUser


You could have two methods - one that returns HTML and another than returns JSON.

Or alternatively create an ActionResult that delegates to a JsonResult if the request is an Ajax request, or a PartialViewResult otherwise eg:

public class AjaxableResult : ActionResult
{

  private readonly JsonResult _jsonResult;
  private readonly PartialViewResult _partialViewResult;

  public AjaxableResult(JsonResult jsonResult, PartialViewResult partialViewResult)
  {
    _jsonResult = jsonResult;
    _partialViewResult = _partialViewResult;
  }      

  public override void ExecuteResult(ControllerContext context)
  {
    if (context.HttpContext.Request.IsAjaxRequest()) {
      _jsonResult.ExecuteResult(context);
    }
    else
    {
      _partialViewResult.ExecuteResult(context);
    }
  }
}
like image 22
Rich O'Kelly Avatar answered Sep 18 '22 14:09

Rich O'Kelly


Why you just make you ajax called and instead of expect a JSON object send to the client the html with a method in your controller of ActionResult remember that this type return the html of the view type like this

 //this if you want get the html by get
 public ActionResult Foo()
 {
    return View();
 }

And the client called like this

$.get('your controller path', parameters to the controler , function callback)

or

$.ajax({
        type: "GET",
        url: "your controller path",
        data: parameters to the controler
        dataType: "html",
        success: your function
    });

Also you can load partial views, and render in a specific parts of your view with the jquery load which it's no more than a ajax called

like image 34
Jorge Avatar answered Sep 22 '22 14:09

Jorge