Asp.Net MVC: Fill a model property from a ActionFilterAttribute OnActionExecuting
-
25-05-2021 - |
题
I'm implementing a captcha control for lost password in a website, like described here
But I feel very unconfortable with the `
filterContext.ActionParameters["captchaValid"] = recaptchaResponse.IsValid;
Because:
- I've a strongly typed view, with validators
- The day I will change the property name without remembering this string field, it won't works.
So I searched how to edit an attribute of my model in the ActionFilterAttribute
, in the OnActionExecuting
, because my controller action will need this data.
I found this, but can't works for me since I need the model to be set BEFORE the action execute.
So I thought that I could add a "Post variable", which will be read by the model binder, but it seems that the filterContext.HttpContext.Request.Form
is in read only mode.
So how do you think I could put the result in my model?
E.g: MyModel.IsCaptchaValid = recaptchaResponse.IsValid;
Event if I can't avoid to specify the property field, it's better than now:
filterContext.Something.Else["ModelKey"] = recaptchaResponse.IsValid;;
解决方案
How about adding an error to ModelState e.g.
filterContext.Controller.ViewData.ModelState.AddModelError("", ""Captcha response invalid")
You can then check for ModelState.IsValid in your action (which you should be doing anyway)
其他提示
The day I will change the property name without remembering this string field, it won't works.
If you are worried about a property / string name change breaking the functionality, you could unit test your custom attribute.
public void CaptchaValidatorAttribute_SetsActionParameter_ForCaptchaValidity()
{
// arrange
var filterContext = new ActionExecutingContext
{
ActionParameters = new Dictionary<string, object>()
// ... other arrangements, like mocking HttpContextBase and HttpRequestBase
};
var actionFilter = new CaptchaValidatorAttribute();
// act
actionFilter.OnActionExecuting(filterContext);
// assert
Assert.AreEqual(filterContext.ActionParameters.ContainsKey("captchaValid"),
true);
}