tags:

views:

119

answers:

2

I'm rendering a page where part of the page is a FORM -- rendered via a partial. The submit button on that form posts to my controller via Ajax (using JQuery .post()). When the controller action takes over there are two possible execution paths:

  1. The form data is valid. In this case the controller updates the database with a new record and then returns an HTML table by rendering a PartialView (and returns a ViewResult).

  2. The form data is invalid. In this case I want to re-render the original form -- with the validation failures highlighted. I believe I can do this with a different PartialView invocation.

On the client side, in the completion javascript function, I have to differentiate between the success and failure cases because the DOM target for the returned HTML will be different. I guess I could inspect the HTML for some known element to differentiate the cases, but it seemed to me that a better solution would be to return a JSonResult that contains a boolean status in one field and the HTML in another.

I know how to return a JsonResult from the controller. However, I need to be able to capture the HTML from the PartialView calls in order to stick that text into the field. Does anyone know:

(a) how to do this, and/or

(b) a better way to approach the situation.

TIA

Update 8/20/2009

I think I am coming close to what I want with this code:

        ViewEngineResult viewEngineResult = ViewEngines.Engines.FindPartialView(this.ControllerContext, "HospitalDoseList");
        ViewData.Model = hospitalStay;
        ViewContext viewContext = new ViewContext(ControllerContext, viewEngineResult.View, this.ViewData, this.TempData);
        using (StringWriter writer = new StringWriter()) {
            viewEngineResult.View.Render(viewContext, writer);
            string html = writer.ToString();
            JsonResult jsonResult = new JsonResult();
            jsonResult.Data = new {Status = true, Html = HttpUtility.HtmlEncode(html)};
            return jsonResult;
        }

However, the html string is coming up blank where I expected it to contain the HTML that would normally be rendered to the response stream via a call to

return PartialView("HospitalDoseList", hospitalStay);
+1  A: 

I would suggest that the easiest thing to do would be to have separate validation and post actions triggered by the submit button. You'd first do an AJAX validation/post that returns JSON status and potentially an array of validation errors (strings). Actually an empty list would probably suffice as evidence of success so you could possibly omit the status. Once you've done your server side validation, then invoke another action via AJAX that would retrieve the data to display. This action would render a partial view and return HTML.

tvanfosson
That's an interesting idea. However, I'd like to leverage the Html.Validation extension methods in the View which display the validation errors in the ViewData's ModelState.
Decker
+1  A: 

I was going to stick this in a comment but it was too much text...

The pattern of returning an AJAX status code is very common, check out my post here: http://stackoverflow.com/questions/1264419/jquery-ajax-responses-in-asp-net-mvc/1264449#1264449 and this blog post: http://www.bennadel.com/blog/1392-Handling-AJAX-Errors-With-jQuery.htm.

As to the partial view, you're a bit out of luck - ViewResults need to have ExecuteResult() called on them, which then renders the html directly to the Response. You'll need to come up with a different strategy, perhaps something like tvanfosson suggested.

womp
I thought I saw something about IView.Render that allowed rendering the view to something other than the Response stream (e.g. a memory stream). I'll do some more digging along those lines...
Decker
I already did that digging.. it doesn't get you too far unfortunately. The problem is that PartialView.View is null until you call ExecuteReader().. and then if you try to call Render() on the View, it just returns an empty string, since it's been rendered and released by the view engine. If you do find a way though, please post it.
womp