Last active
August 25, 2019 09:42
-
-
Save ferventcoder/4735084 to your computer and use it in GitHub Desktop.
Interesting Dilemna
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
http://stackoverflow.com/a/5188833 for what we based our solution | |
on. | |
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 file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This is based loosely on http://stackoverflow.com/a/12024227 | |
public class SetTempModelStateAttribute : ActionFilterAttribute | |
{ | |
public override void OnActionExecuted(ActionExecutedContext filterContext) | |
{ | |
base.OnActionExecuted(filterContext); | |
filterContext.Controller.TempData[ApplicationParameters.Web.ModelState] = filterContext.Controller.ViewData.ModelState; | |
} | |
} | |
public class MergeModelStateAttribute : ActionFilterAttribute | |
{ | |
public override void OnActionExecuting(ActionExecutingContext filterContext) | |
{ | |
base.OnActionExecuting(filterContext); | |
if (!filterContext.Controller.TempData.ContainsKey(ApplicationParameters.Web.ModelState)) return; | |
var tempModelState = filterContext.Controller.TempData[ApplicationParameters.Web.ModelState] as ModelStateDictionary; | |
if (tempModelState != null) | |
{ | |
filterContext.Controller.ViewData.ModelState.Merge(tempModelState); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[HttpPost] | |
[SetTempModelState] | |
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. | |
if(!ModelState.IsValid) | |
{ | |
return ReturnPartialOrRedirect("_CommentAdd", model, model.Url); | |
} | |
//actions for saving... | |
return ReturnPartialOrRedirect("_Success", new SuccessModel{Message="Some message"}, model.Url); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//no explicit opt in necessary | |
public static void RegisterGlobalFilters(GlobalFilterCollection filters) | |
{ | |
filters.Add(new MergeModelStateAttribute()); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//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); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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:
http://stackoverflow.com/questions/4523827/asp-net-mvc-what-does-isajaxrequest-actually-mean
The chances that you are using a JS library that does not set the required header is low.