0

I have one asp.net mvc 3 application.

public ActionResult Students()
{ 
  return View();
}

When i request these actions thru browser, everything works fine. It returns appropriate views, but when such actions are called from another site(across domain) thru jQuery Ajax call, It give transport error.

as a result we need to return such views in JsonpResult type, but now the problem is how do browser load such views of type JsonpResult ? it doesn't return html part of the view instead it asks browser to save view result of type Jsonp.

Any suggestion, how to solve this ?

thanks.

Joe
  • 47
  • 1
  • 6
  • I don't understand why you want to return a complete view (html document) in an ajax call? Ajax calls are mainly for pieces of data in expressed json, xml or html (partial view?). – VJAI Sep 26 '12 at 13:50

1 Answers1

0

You could use the RenderPartialViewToString method shown in this answer to render the view to a string and then return the custom JsonpResult you have written:

public class StudentsController : Controller
{
    public ActionResult Index()
    {
        MyViewModel model = ...
        return new JsonpResult(new 
        {
            html = RenderViewToString("Index", model)
        });
    }

    public string RenderViewToString(string viewName, object model)
    {
        ViewData.Model = model;
        using (var sw = new StringWriter())
        {
            var viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
            var viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
            viewResult.View.Render(viewContext, sw);
            viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View);
            return sw.GetStringBuilder().ToString();
        }
    }

    protected string RenderPartialViewToString(string viewName, object model)
    {
        if (string.IsNullOrEmpty(viewName))
        {
            viewName = ControllerContext.RouteData.GetRequiredString("action");
        }

        ViewData.Model = model;
        using (var sw = new StringWriter())
        {
            var viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
            var viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
            viewResult.View.Render(viewContext, sw);
            return sw.GetStringBuilder().ToString();
        }
    }
}

The JsonpResult class used here could be found in this post.

And now you could invoke this controller action using AJAX from another domain:

var url = 'http://example.com/students/index';
$.getJSON(url + '?callback=?', function (data) {
    alert(data.html);
});
Community
  • 1
  • 1
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • Whether RenderPartialViewToString method will return View ?? – Joe Sep 26 '12 at 09:27
  • No, it returns a string. The first parameter is the view name and the second is the model. It will simply execute this view and return the result to a string that we are embedding into the `JsonpResult`. – Darin Dimitrov Sep 26 '12 at 09:27
  • sorry for a dumb question, but controller action which returning View will get replaced with "return new JsonpResult(.. ", whether browser will recognize this (html) ? however this is a preliminary assumption, let me give a try first. – Joe Sep 26 '12 at 09:31
  • I have slightly modified the controller action and added the `RenderViewToString` method in addition to `RenderPartialViewToString`. You should use the one that suits your needs. For example if you want to return the full markup with a Layout then use `RenderViewToString`. – Darin Dimitrov Sep 26 '12 at 09:33
  • having error at `return new JsonpResult(new { html = RenderViewToString("Index", model) });` – Joe Sep 26 '12 at 09:40
  • error is: JsonpResult has 0 parameter(s) but is invoked with 1 argument(s) , whether JsonpResult class needs to have a property html ? – Joe Sep 26 '12 at 09:47
  • Ooopps... My bad! I was referring wrong `JsonpResult` class, now ok, error gone... Now after these changes, i am getting all html contents, but when requesting Url from Browser like [link]http://Mysite/Controller/Action , it asks me to 'save as', means it is not recognizing html content, any idea how to solve this ? – Joe Sep 26 '12 at 10:16
  • You could check whether the `callback` request parameter is present and then return a standard View instead of JsonpResult. – Darin Dimitrov Sep 26 '12 at 10:20
  • Thanks, after doing all you mentioned changes, my action result returns appropriate jsonp/html data, things seems to be fine this side, but when focusing to ajax call: It is still giving me, errorThrown = **transport error** , My ajax get call resided in dynamic script content which is a part of different (sub-domain) application. Any idea how to solve/troubleshoot ? – Joe Sep 27 '12 at 03:52
  • `code` $.get("http://Mysite/Controller/Action?callback=") .success(function (data) { alert(data.html); $("#placeholder").html(data.html); }) .error(function (jqXhr, textStatus, errorThrown) { alert(jqXhr + "-" + textStatus + "-" + errorThrown); }); `code` – Joe Sep 27 '12 at 03:56