Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Interesting Dilemna
Say you are in a world where you want to use progressive enhancement (sometimes for accessibility)
with ASP.NET MVC 3+.
Progressive Enhancement means the site WORKS WITHOUT JAVASCRIPT FOLKS.
Now say you have something like comments that will be on multiple pages.
You want the site to be maintainable so you want to use a partial with
form submission.
This means that the partial will submit to a different controller than
the page you are currently on.
When Javascript is turned on, you use progressive enhancement
to ajax the form submission (jquery post) and the only part
of the page that reloads is the form area. You also use
client side validation.
When Javascript is turned off, you are submitting to a different
url. But when there are validation errors you need to present
the same page you were on. But how do you do that?
This outlines a possible solution.
You still need a way to tell the server that Javascript is on
and we've implemented this, but we are not happy with it, so
I left that part out of this example. Please see for what we based our solution
We have an explicit opt in to share the ModelState, but every action
implicitly will opt in to merge it automatically. And if Javascript
is enabled, we don't even use this code.
// This is based loosely on
public class SetTempModelStateAttribute : ActionFilterAttribute
public override void OnActionExecuted(ActionExecutedContext filterContext)
filterContext.Controller.TempData[ApplicationParameters.Web.ModelState] = filterContext.Controller.ViewData.ModelState;
public class MergeModelStateAttribute : ActionFilterAttribute
public override void OnActionExecuting(ActionExecutingContext filterContext)
if (!filterContext.Controller.TempData.ContainsKey(ApplicationParameters.Web.ModelState)) return;
var tempModelState = filterContext.Controller.TempData[ApplicationParameters.Web.ModelState] as ModelStateDictionary;
if (tempModelState != null)
public ActionResult AddComment(CommentModel model)
// One might pull the url the request is from (we will need to deal with this eventually) or pass it as a parameter.
// What we've done with it as part of the model is a short circuit that we are not happy with using.
return ReturnPartialOrRedirect("_CommentAdd", model, model.Url);
//actions for saving...
return ReturnPartialOrRedirect("_Success", new SuccessModel{Message="Some message"}, model.Url);
//no explicit opt in necessary
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
filters.Add(new MergeModelStateAttribute());
//this goes in a global controller that inherits controller that all controllers for your site inherit from
public ActionResult ReturnPartialOrRedirect<T>(string viewName, T model, string redirectUrl)
if (ApplicationParameters.IsJavaScriptEnabled)
return PartialView(viewName, model);
return Redirect(redirectUrl);

dipunm commented Aug 20, 2013

Instead of checking whether the user can use javascript (or has it enabled), Could you not simply check whether the call was an Ajax call?

Request.IsAjaxRequest(); will be true if the request was made using Ajax:

The chances that you are using a JS library that does not set the required header is low.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment