ASP.NET MVC Non English URL Request Validation Exception - c#

In my ASP.NET MVC 2 application, I have this encoded image url -
<img src="/Image?Selected_Nme=Mayag%26%23252%3Bez%2C%20PR/>
The uncoded Selected_Nme is "Mayagüez, PR".
I will get an exception error like this -
[HttpRequestValidationException (0x80004005): A potentially dangerous Request.QueryString value was detected from the client (amp;Selected_Nme="Mayagüez, PR").]
Then I decorated my action in controller with "[ValidateInput(false)]", like this -
[ValidateInput(false)]
[HttpGet]
[OutputCache(CacheProfile = "test")]
public ActionResult Image(string Selected_Nme = ""){
...
}
I still see the same error after this.
What can I do to eliminate the problem?
Thanks,

You need to configure the requestValidationMode:
<system.Web>
...
<httpRuntime requestValidationMode="2.0"/>
From Request Validation in ASP.NET:
You can disable request validation for an entire application, but
doing so is not recommended. The recommendation is to selectively
disable request validation only for the virtual paths or specific
pages where you want to allow markup.
In either case, you must make two changes in the Web.config file. The
first change is to set the requestValidationMode attribute of the
httpRuntime element to "2.0". This setting makes request validation
occur later in the sequence of request processing events. The setting
is required for applications that use ASP.NET 4 and later, because as
of ASP.NET 4, request validation takes place earlier in the request
life cycle than it did in previous versions of ASP.NET
One last worthwhile note. Using [ValidateInput(false)] disables validation for all data sent into the method. If you would still like to keep validation in place for any other properties being sent, you can disable the validation on a specific property of a class:
public class SomeModel {
[AllowHtml]
public string Selected_Nme { get; set; }
// this property will still be validated!
public string PleaseDontXSSMe { get; set; }
}

Related

ASP.NET Core 6 WebAPI, invalid model does not reach the action method, instead instantly returns with HTTP 400

I've created a WebAPI project in VS 2022, using .NET 6
I've annotated my model's Customer class CustomerId property with [MaxLength(5)] and [MinLength(5)] attributes.
[Route("api/[controller]")]
[ApiController]
public class CustomerController : ControllerBase
{
private readonly NorthwindContext _ctx;
// ...
[HttpPost]
public Customer Insert(Customer customer)
{
// Method never called. Somewhere the pipeline instantly
// sends the HTTP 400 response with the correct error message.
if (!ModelState.IsValid)
{
}
If I call the API with invalid data, say 4 or 6 lenght CustomerId, then the Insert method never called. Somewhere the pipeline instantly sends the HTTP 400 response with the correct validation error message
Question
It is not clear, then when will be the ModelState.IsValid false? Can I configure the pipeline to allow the method to be called?
It is not clear, then when will be the ModelState.IsValid false?
Well, in a nutshell, in MVC controller; if you haven't set any annotation on property by default its required means not null. So if you don't pass the value your ModelState.IsValid will always be false. Usually Model state represents errors that come from two subsystems.
For instances, model binding and model validation which means request firstly goes to the model validator once it meet the condition then it route to the specific controller other than, controller doesn't get hitted.
Thus, your ModelState.IsValid would always be false when any property you would set required and that's value wouldn't be passed while you submitting request for your scenario Insert. So, yes any property without nullable ? would require to pass during request submission, other than your ModelState.IsValid would always be false.
Let's consider, your Customer Class you have set few validation constrains on CustomerId if this is not null; it will firstly reach to model binding and if it doesn't meet your condition it will throw validation message from there and it wouldn't hit controller.
So if you don't pass the value for non nullable property or your property violate any condition it will restrict you from submitting request.
Why then your ModelState.IsValid doesn't reach?
As you are using Web API controller and in Web API controllers don't have to check ModelState.IsValid if they have the ApiController attribute. In that case, an automatic HTTP 400 response containing error details is returned when model state is invalid.
Can I configure the pipeline to allow the method to be called?
Of course you can. In that scenario, you have to disable the automatic 400 behavior. You might know ConfigureApiBehaviorOptions within builder.Services.AddControllers and you will get a property called SuppressModelStateInvalidFilter we have to set this property to true. Please have a look on following code snippet:
builder.Services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
options.SuppressModelStateInvalidFilter = true;
});
Output:
Note:
If you would like to know more details on Model state Validation and automatic 400 response you could check our official document here.
With the nullability in .Net 6/.Net 7, the data you send to the Web API has to match the model or this will happen.
public class MyModel
{
public int SomeId { get; set; }
public int? ForeignId { get; set; }
public string? SomeName { get; set; }
public string RequiredName{ get; set; }
}
MyModel myData = new()
{
SomeId = 5,
ForeignId = 9,
SomeName = "Test",
RequiredName = null
}
var myResult = MyWebAPICall(myData);
Since the RequiredName is defined as not nullable, the Web API will reject it and send back the 400.
You have to go through the models / DTO's and make sure what you defined matches your data source (database, etc.) so it will save properly and focus on what fields need to allow nulls. The nullability really forces you to go through everything.

FromBody attribute

I have a method as described below which get user as parameter.
To send the user parameter values, I am using postman request/response tool.
My question is, if the request already have user parameter in body request (see at the postman print screen ) why do I need to directly specify [FromBody] in action controller? When this attribute removed, parameter send with null values.
Thanks
[HttpPost("register")]
public IActionResult Register([FromBody]User user)
{
//.. code here
}
public class User
{
public string Name { get; set; }
public string Password { get; set; }
}
The [FromBody] directive tells the Register action to look for the User parameter in the Body of the request, rather than somewhere else, like from the URL. So, removing that confuses your method, and that's why you see null values as it's not sure where to look for the User parameters.
See: https://learn.microsoft.com/en-us/aspnet/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api for more information/learning.
For Model Binding in ASP.NET Core, MVC and Web APi uses the same model binding pattern.
There are default model bindings like Form Values, Route values and Query Strings. If these bindings fails, it will not throw an error, and return null.
If you do not want to add [FromBody], you could try Form Values binding and send request from Postman like below:
[FromBody] will override default data source and specify the model binder's data source from the request body.
You could refer Model Binding in ASP.NET Core for detail information
the attribute [FromBody] ensures the API reads the JSON payload in the postman body. For more info, read
https://learn.microsoft.com/en-us/aspnet/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api

Remote Validator on Model in MVC4 to /api/ Route

How does one configure a Remote validator via data annotations to make its call at /api/{controller} instead of /{controller}/{action}?
My model:
public class MyModel
{
[Required]
public string Name { get; set; }
[EmailAddress(ErrorMessage="We need a valid email."), Remote(....)]
public string Email { get; set; }
}
No matter what I try, the URL called by that remote validator is /foo/bar instead of just doing a get to /api/foo.
Is there any support for WebAPI in remote validators?
I'd like my email uniqueness check to use the .NET validators if at all possible (rather than having to do it manually), my form is submitted via AJAX, I'd like to validate the email prior to form submission, and using a remote validator pointing at an API controller seems like a natural choice.
Cannot use a Web API controller. This is a limitation of the RemoteAttribute. To avoid conflicts with MVC controllers, to match a Web API route you must include an httproute key, which RemoteAttribute doesn't do.
You should be able to inherit RemoteAttribute and override GetUrl to make it work.

Problem with remote validation in asp.net mvc 3

I have a Person Model
public class Person
{
public int ID { get; set; }
[Required]
[Remote("UserNameExists", "People", "Username is already taken.")]
public string Name { get; set; }
[Required]
public string LastName { get; set; }
}
This is my UserNameExists method
public JsonResult UserNameExists(string name)
{
bool exists = personRepository.GetPersonByName(name.Trim());
if (!exists)
return Json(true, JsonRequestBehavior.AllowGet);
return Json(string.Format("{0} is not avavfddvilable.", name),
JsonRequestBehavior.AllowGet);
}
When I have Javascript enabled it works just fine but when I disable javascript this rule is not enforced...
Why is this?
Please Help.
Edit for expected behavior:
According to msdn it should respect this rule even without Javacript
Optionally, disable client script in your browser, run the page again,
and enter data that violates the
validation constraints.
As you leave the field that contains
the invalid data, you do not see a
validation error because scripting is
disabled. Because ASP.NET MVC is using
unobtrusive JavaScript, you do not see
client-side script errors. However,
server-side validation is performed
when you submit the form. (It is a
good practice to test your Web
application with a browser that has
scripting disabled.)
See my MSDN article How to: Implement Remote Validation in ASP.NET MVC I use the remote client validation code in the HttpPost Create method to test server side when JavaScript is disabled.
[HttpPost]
public ActionResult Create(CreateUserModel model) {
// Verify user name for clients who have JavaScript disabled
if (_repository.UserExists(model.UserName)) {
ModelState.AddModelError("UserName", ValidationController.GetAltName(model.UserName, _repository));
return View("Create", model);
}
You must duplicate a validation call on the server - this DOES NOT work as outlined as per my testing.
See my post at:
DRY Remote Validation in ASP.NET MVC 3
It sounds like you have JavaScript disabled, and your Remote Validation fails.
Remote Validation requires JavaScript enabled in the browser. It's using jQuery and an AJAX call to get this done.
The quote from MSDN is exactly what you're observing:
you do not see a validation error
server-side validation is performed when you submit the form

ASP.NET MVC: Filtering/Varying by HTTP Status Code in OutputCache Attribute

In the ASP.NET MVC site that I'm writing, I'm building a generic Error Action that is routed to by an HttpModule, following this tutorial. In this Action, I will return a View corresponding to the status code that is applied to the response inside the HttpModule (after doing this, the module transfers the request over to the Action in question).
That's all good, except that I want to implement caching. I don't want to use the OutputCache attribute without filtering/varying, because that would mean that the page would be cached once. I want the page to be cached once for every possible status code.
Is it possible to somehow filter/vary with OutputCacheAttribute's properties, so that each Response.StatusCode is cached separately?
How are you currently handling the routing to your error action, e.g. you could have:
/Errors/404
/Errors/500
All pointing to the exact same action, and the caching will be handled for you because they are independent urls and you apply the OutputCache attribute a single time to the generic error action:
[OutputCache]
public ActionResult DisplayError(int errorCode) {
return View(errorCode.ToString());
}
Would that work?

Categories

Resources