Sunday, October 02, 2011

Developing for MVC4 using Razor and JSON

Just playing around this weekend, I wanted some data listings in a page that did not post back in MVC. While not such a big deal in regular ASP, MVC does not have page event handlers in a code-behind file. There is instead a Controller class that you can call in Routing code.



First : the client side javascript handler, this is what is called when the Controller method completes.



using (Ajax.BeginForm("SearchForms", "DBForms", new AjaxOptions() { OnSuccess="jsonFSearchComplete", OnFailure="searchFail" })) Then … function jsonFSearchComplete(context) { $("#DBFormsDiv").html(context.Data); }



Next, the Razor syntax for the page :


@{using (Ajax.BeginForm("JsonSearchRequests",
"Request",
new AjaxOptions() {
OnComplete = "searchComplete",
OnFailure= "searchFail"
}))

// Not including the whole form I created here, just
// labels and textboxes, etc..
}





Then the Controller code for getting the Partial view built and sent down (Got this from StackOverflow postings):


private string RenderRazorViewToString(string viewName)
{
using (var sw = new System.IO.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();
}
}


For a form posting in a page, there must be a Controller method ( :


[AcceptVerbs(HttpVerbs.Post)]
public JsonResult JsonSearchRequests(string AccountNumber,
string Subfirm,
string RegistrationType)
{
Data d = new Data();

if (AccountNumber.Length > 0)
{
ViewData["Requests"] =
d.GetRequestsByAccount(AccountNumber);
}
else if (Subfirm.Length > 0)
{
ViewData["Requests"] =
d.GetDBRequests(Subfirm, RegistrationType)
.Skip(0).Take(100);
}
return Json(new { Data = RenderRazorViewToString("dbRequests") });
// Note the HttbVerb must be stated for Posting a form
}


For a link that a user can click in the page :



[AcceptVerbs(HttpVerbs.Get)]
public JsonResult JsonSelectDbRequest(string Id)
{
Data d = new Data();
ViewData["Generations"] = d.GetGenerations(Id);

return Json(new { Data = RenderRazorViewToString("dbGenerations") },
JsonRequestBehavior.AllowGet);
}

// Note the Http Verb for GET must be stated
}



Code for a Partial View of a list that does Ajax posting :


@Ajax.ActionLink("SELECT",
"JsonSelectDbRequest",
"DocRequest",
new { Id = req.REQUEST_ID },
new AjaxOptions() { OnComplete = "requestSelectComplete" });



EDIT: There is no need to include the old MVCAjax script files.

1 comment:

Brian O said...

Remember to use ONSUCCESS not ONCOMPLETE, as that will alleviate the need to parse JSON in the client side.