This is a view:
@model ModelValidation.Models.Appointment
@{
ViewBag.Title = "Make a Booking";
}
<h2>
Book an Appointment</h2>
@using (Html.BeginForm())
{
<p>
@Html.LabelFor(m => m.ClientName, "Your name: ") @Html.EditorFor(m => m.ClientName)
</p>
<p>
@Html.LabelFor(m => m.Date, "Appointment Date: ") @Html.EditorFor(m => m.Date)
</p>
<p>
@Html.EditorFor(m => m.TermsAccepted) @Html.LabelFor(m => m.TermsAccepted, "I accept the terms & conditions")
</p>
<input type="submit" value="Make Booking" />
}
This is the Appointment class:
public class Appointment
{
public string ClientName { get; set; }
[DataType(DataType.Date)]
public DateTime Date { get; set; }
public bool TermsAccepted { get; set; }
}
If I enter into the ClientName editor something like this:
<b>asdf</b>
after I press the "Make Booking" button (submit) I get the following exception:
[HttpRequestValidationException (0x80004005): potentilly dangerous value of Request.Form has been received from the client (ClientName="<b>asdf</b>").]
System.Web.HttpRequest.ValidateString(String value, String collectionKey, RequestValidationSource requestCollection) +8755668
Microsoft.Web.Infrastructure.DynamicValidationHelper.<>c__DisplayClass12.<ReplaceCollection>b__d(String value, String key) +79
Microsoft.Web.Infrastructure.DynamicValidationHelper.LazilyEvaluatedNameObjectEntry.ValidateObject() +89
Microsoft.Web.Infrastructure.DynamicValidationHelper.LazilyValidatingHashtable.get_Item(Object key) +54
System.Collections.Specialized.NameObjectCollectionBase.FindEntry(String key) +20
System.Collections.Specialized.NameValueCollection.GetValues(String name) +8
System.Web.Mvc.ValueProviderResultPlaceholder.GetResultFromCollection(String key, NameValueCollection collection, CultureInfo culture) +20
System.Web.Mvc.<>c__DisplayClass4.<.ctor>b__0() +16
System.Lazy`1.CreateValue() +361
System.Lazy`1.LazyInitValue() +9591042
System.Lazy`1.get_Value() +89
System.Web.Mvc.NameValueCollectionValueProvider.GetValue(String key, Boolean skipValidation) +68
System.Web.Mvc.ValueProviderCollection.GetValueFromProvider(IValueProvider provider, String key, Boolean skipValidation) +55
System.Web.Mvc.<>c__DisplayClass9.<GetValue>b__4(IValueProvider provider) +33
System.Linq.WhereSelectEnumerableIterator`2.MoveNext() +151
System.Linq.WhereSelectEnumerableIterator`2.MoveNext() +177
System.Linq.Enumerable.FirstOrDefault(IEnumerable`1 source) +4187840
System.Web.Mvc.ValueProviderCollection.GetValue(String key, Boolean skipValidation) +272
System.Web.Mvc.DefaultModelBinder.BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) +385
System.Web.Mvc.DefaultModelBinder.GetPropertyValue(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor, IModelBinder propertyBinder) +17
System.Web.Mvc.DefaultModelBinder.BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor) +399
System.Web.Mvc.DefaultModelBinder.BindProperties(ControllerContext controllerContext, ModelBindingContext bindingContext) +93
System.Web.Mvc.DefaultModelBinder.BindComplexElementalModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Object model) +53
System.Web.Mvc.DefaultModelBinder.BindComplexModel(ControllerContext controllerContext, ModelBindingContext bindingContext) +1367
System.Web.Mvc.DefaultModelBinder.BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) +449
System.Web.Mvc.ControllerActionInvoker.GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor) +317
System.Web.Mvc.ControllerActionInvoker.GetParameterValues(ControllerContext controllerContext, ActionDescriptor actionDescriptor) +117
System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +343
System.Web.Mvc.Controller.ExecuteCore() +116
System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) +97
System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext) +10
System.Web.Mvc.<>c__DisplayClassb.<BeginProcessRequest>b__5() +37
System.Web.Mvc.Async.<>c__DisplayClass1.<MakeVoidDelegate>b__0() +21
System.Web.Mvc.Async.<>c__DisplayClass8`1.<BeginSynchronous>b__7(IAsyncResult _) +12
System.Web.Mvc.Async.WrappedAsyncResult`1.End() +62
System.Web.Mvc.<>c__DisplayClasse.<EndProcessRequest>b__d() +50
System.Web.Mvc.SecurityUtil.<GetCallInAppTrustThunk>b__0(Action f) +7
System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Action action) +22
System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +60
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +9
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +8862381
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +184
As far as I know all the user input is encoded by default in razor view engine. Then why am I getting this?
The exception is thrown before the target POST action method is invoked. Or what am I missing?
There isn't technically anything wrong with storing HTML in your data layer but it can increase your with of xss (cross site scripting) attacks with malicious HTML/script.
Use the
attribute on your ClientName property. Then prior to save use the anti-xss library from Microsoft WPL or Web Protection Library and use the to sanitize it (not encode!) before saving to your database.If you want much more extended information on request validation and xss attacks see my pluralsight.com hack proofing course.
Edit:
Sorry read that all wrong.
The MVC framework by default will try and protect you from dangerous input, such as html. This can be used to attack your site if you later re-render it. See Cross Site Scripting
If you want to accept HTML like the value you are entering for the name, you will have to explicitly tell it not to validate that input.
Like:
I would of course recommend against this unless it is a specific requirement.