views:

84

answers:

3

I want to know if it is possibe to return a view as a JSON object. In my controller I want to do something like the following:

        [AcceptVerbs("Post")]
        public JsonResult SomeActionMethod()
        {
            return new JsonResult { Data = new { success = true, view = PartialView("MyPartialView") } };
        }

In html:

 $.post($(this).attr('action'), $(this).serialize(), function(Data) {
                        alert(Data.success);
                        $("#test").replaceWith(Data.view);

                    });

Any feedback greatly appreciated.

A: 

Why would you return the view encapsulated in a JSON object? It will probably work, but it's an open door for the next developer to say "WTF?!?"

Why not just having your action return the PartialView calling $.get() and injecting it, or even better calling

$("#target").load(url);

EDIT:

Well, since you are posting values, you could use get or load, obviously, but your approach still doesn't make much sense... I suppose you are going to apply some changes depending on the success variable in your json object that your return. But you should better keep this kind of logic on the server side, and return one view or another depending on your conditions. You could return a JavascriptRersult for example that will execute the piece of javascript as soon as it is retrieved... Or return 2 different PartialViews.

Stephane
Thanks for the reply Steph - please see my comments to Thomas's post above
Chev
A: 

Take a look at this example http://geekswithblogs.net/michelotti/archive/2008/06/28/mvc-json---jsonresult-and-jquery.aspx

You should be able to return this.Json(obj) where obj is just the data you want to serialize.

Also if you use the $.getJSON or $.ajax method with the type set to 'json' then the result will automatically be converted to a javascript object on the client so you have the data to work with instead of a string.

Lee
+3  A: 

I would really not recommend this approach - if you want to make sure the call was a success, use the HTTPHeader that is built-in in the protocol and in the jQuery library. If you take a look at the API documentation for $.ajax you'll se that you can have different reactions to different HTTP status codes - there are, for example, success and error callbacks. With that approach, your code would look something like

$.ajax({
    url: $(this).attr('action'),
    type: 'POST',
    data: $(this).serialize(),
    dataType: 'HTML',
    success: function(data, textStatus, XMLHttpRequest) { 
                 alert(textStatus);
                 $('#test').html(data); 
             },
    error: function(XmlHttpRequest, textStatus, errorThrown) {
               // Do whatever error handling you want here.
               // If you don't want any, the error parameter
               //(and all others) are optional
           }
    }

And the action method simply returns the PartialView:

public ActionResult ThisOrThat()
{
    return PartialView("ThisOrThat");
}

But yes, it can be done your way too. The problem with your approach is that you're returning the PartialView itself, rather than the output HTML. Your code would work if you changed it to this:

public ActionResult HelpSO()
{
    // Get the IView of the PartialView object.
    var view = PartialView("ThisOrThat").View;

    // Initialize a StringWriter for rendering the output.
    var writer = new StringWriter();

    // Do the actual rendering.
    view.Render(ControllerContext.ParentActionViewContext, writer);
    // The output is now rendered to the StringWriter, and we can access it
    // as a normal string object via writer.ToString().

    // Note that I'm using the method Json(), rather than new JsonResult().
    // I'm not sure it matters (they should do the same thing) but it's the 
    // recommended way to return Json.
    return Json(new { success = true, Data = writer.ToString() });
}
Tomas Lycken
Thanks Thomas - I appreciated the pointer re best practices, but I am not looking at a 200 or 500 error. This is more suited to validation where I am returning a success and then returning the relevant partial view. There is a view for success and failure, BUT I still need to do some processing elsewhere on the page after the result is returned. I kept the example as simple as possible to get a technical answer as opposed a design one. Thanks again for the reply!
Chev
Thomas - using mvc 1.0 I dont have access to the ControllerContext.ParentActionViewContext property?
Chev
Hm... The code I showed was obviously from MVC 2 with .NET 4, since that's what I'm working with. I'll take a look around for some way to do it in MVC 1 - but my search algorithm will be "ah, intellisense - hm, what's this?", so you can probably find it just as well as I can :P
Tomas Lycken