ASP.NET Misconfiguration Improper Model Validation (CWE ID 1174) - asp.net-mvc

I am creating an ASP.NET MVC application.
I have a model with data annotations like this:
public class SearchModel
{
[MaxLength(11)]
public string? SSN { get; set; } = string.Empty;
}
And I have a controller method that receives an object of this type as parameter:
public async Task<IActionResult> Search([Bind(include: "SSN")] SearchModel searchModel)
{
// do something
}
I get a Veracode error
ASP.NET misconfiguration : improper model validation (CWE ID 1174)
on the definition of the method...
Testing.. If I replace SearchModel with String, it works. So the problem is the model definition, but I added the data annotations to the property.
What else can I check?
Thanks

As I found here the only way to avoid this flaw is to remove signature Async Task<> from the Method..

Related

asp.net mvc form values display

I'm new to asp.net mvc. Basically i'm from php programmer. In my php file i can display what are all the values coming from html page or form using echo $_POST; or print_r($_POST); or var_dump($_POST). But in asp.net how can i achieve this to check what are all the values are coming from UI Page to controller.
You may take a look at the Request.Form property:
public ActionResult SomeAction()
{
var values = Request.Form;
...
}
You could put a breakpoint and analyze the values. Or simply use a javascript development toolbar in your browser (such as FireBug or Chrome Developer Toolbar) to see exactly what gets sent to the server.
But normally you are not supposed to directly access the raw values. In ASP.NET MVC there's a model binder which could instantiate some model based on the values sent to the server.
For example you could have the following model:
public class MyViewModel
{
public int Age { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
and then have your controller action take this model as parameter:
public ActionResult SomeAction(MyViewModel model)
{
... you could use the model properties here
}
and now you could invoke this controller action either wityh a GET request passing the parameters in the query string (/someaction?age=10&firstname=foo&lastname=bar) or using a POST and sending them in the body.
You can check the raw data via Request.Form.
But this is not he spirit of the ASP.NET MVC. It is preferd that you expect a model into your controller. You have all type safety mapping already done by special module called model binder.
So unless you work on some special case, you just add a model to the controller action:
public ActionResult SomeAction(SomeModel model)
{
//Handle SomeModel data further ...
}
You can create an action which will accept the parameters from the UI page like the following:
[HttpPost]
public ActionResult SomeAction(string param1, int param2)
{
//Now you can access the values here
}
or make an action which will accept the model
public ActionResult SomeAction(SomeModel model)
{
//Access the model here
}

Where to bind DTO into domain model

I'm starting to use AutoMapper and some doubts arose.
Where is the correct way to map a dto into a domain model?
I'm doing this:
DTO:
public class PersonInsert
{
[Required]
public string Name { get; set; }
public string LastName { get; set; }
}
Action:
[HttpPost]
public ActionResult Insert(PersonInsert personInsert)
{
if (ModelState.IsValid)
{
new PersonService().Insert(personInsert);
return RedirectToAction("Insert");
}
return View("Insert");
}
Service:
public class PersonService
{
public int Insert(PersonInsert personInsert)
{
var person = Mapper.Map<PersonInsert, Person>(personInsert);
return new PersonRepository().Insert(person);
}
}
Repository:
public class PersonRepository
{
internal int Insert(Person person)
{
_db.Person.Add(person);
_db.SaveChanges();
return person.Id;
}
}
So, is this correct? should my service knows about domain? or should I make the bind in repository only? is correct to use [Required] in DTO?
I would almost never create an entity from a DTO - I explain why below. I would use a request object to allow a factory method to build the entity:
Request:
public class InsertPersonRequest
{
[Required]
public string Name { get; set; }
public string LastName { get; set; }
}
Action:
[HttpPost]
public ActionResult Insert(InsertPersonViewModel viewModel)
{
if (ModelState.IsValid)
{
InsertPersonRequest request = InsertPersonViewModelMapper.CreateRequestFrom(viewModel);
new PersonService().Insert(request );
return RedirectToAction("Insert");
}
return View("Insert");
}
Service:
public class PersonService
{
public int Insert(InsertPersonRequest request)
{
var person = Person.Create(request.name, request.LastName);
return new PersonRepository().Insert(person);
}
}
Repository stays the same.
This way all logic for creating the Person are located in the Factory method of the person, and so business logic is encapsulated in the domain - derived fields, default fields etc.
The problem with what you are doing is that the DTO has to be created in the UI, then all fields are mapped to the entity - this is a sure fire way for business logic to seep into the service layer, UI, or anywhere it is not supposed to be.
PLease read that again - This is a very serious mistake I see made time and time again.
I would however, use AutoMapper in the service layer to return a DTO:
Service:
public class PersonService
{
public PersonDto GetById(intid)
{
var person = new PersonRepository().GetById(id);
var personDto = Mapper.Map<Person, PersonDto>(person);
return personDto
}
}
Is this correct?
I personally don't see anything wrong with having your service do the mapping
Is it correct to use [Required] in DTO
No, DTOs should have no business logic whatsoever. They should be used purely for transmitting data across different tiers/layers of your application.
DataAnnotations are typically used on ViewModels for client/server side validation, therefore, I would add another separation into your model and introduce a ViewModel for your Insert action e.g.
public class PersonViewModel
{
[Required]
public string Name { get; set; }
public string LastName { get; set; }
}
public class PersonDto
{
public string Name { get; set; }
public string LastName { get; set; }
}
Action:
[HttpPost]
public ActionResult Insert(PersonViewModel personViewModel)
{
if (ModelState.IsValid)
{
var personDto = Mapper.Map<PersonViewModel, PersonDto>(personViewModel);
new PersonService().Insert(personDto);
...
}
...
}
}
Service:
public class PersonService
{
public int Insert(PersonDto personDto)
{
var person = Mapper.Map<PersonDto, Person>(personDto);
return new PersonRepository().Insert(person);
}
}
It may seem overkill in this scenario (considering the only difference is the [Required] attribute). However, in a typical MVC application you would want to ensure a clean separation between your ViewModels and your business models.
I would say that your PersonService could be seen as part of the domain layer (or Application layer directly above the domain) of your architecture and the controller and DTO is in a layer above that. That means you shouldn't have a reference to the DTO in your PersonService signatures and instead use the domain Person class here. So the Mapping code should go into the Controller. This ensures that your domain logic is not affected by changes to the webservice contract which could really be just one way to use your PersonService.
I would also introduce an interface for your repository which is injected into your PersonService because the PersonService again shouldn't need to know about concrete data access implementations.
As for the [Required] attribute, I don't see a problem with having this on the DTO because it just states the data contract of your webservice method. Anybody calling your webservice should adhere to this data contract. Of course this requirement will typically also be reflected somewhere in your domain code, maybe by throwing an exception etc.
In ASP.NET MVC the typical use of DTO is being part of something called viewmodel. Viewmodel is a class that will combine one to several DTOs into one class tailored for view presentation and posting values back to server.
What you doing is correct, no issues with that, but data annotations should reside on view models, rather than DTOs. Unless you call your DTO a view model, then its fine.
Please read the following posting about model (Domain Model) vs ViewModel in ASP.NET MVC world:
ASP.NET MVC Model vs ViewModel
Confused with Model vs ViewModel
Hope this helps
I think it is fine to have annotations on the DTOs, such as [Required], MaxLength, Range etc.
Your DTO can come in from any (possibly untrusted) source (Not just your website, but from another endpoint, WCF service, etc). All requests will be funneled to your Service/Business Layers, so you will need to validate the input before performing your business logic (simple guard checks). Having the annotations on the DTO simply describe the needed input to perform the task at hand. Passing an object with annotations is not peforming validation.
However, I believe you should be validating the DTO information is correct in the service/business layer (and annotations are a nice way to check this).
Just my thoughts on the situation :)

ASP.NET MVC ModelState is always valid with Fluent Validation

I am trying to use fluent validation with ASP.NET MVC project. I am trying to validate my view model.
This is my viewmodel,
[Validator(typeof(ProductCreateValidator))]
public class ProductCreate
{
public string ProductCategory { get; set; }
public string ProductName { get; set; }
....
}
This is my validator class,
public class ProductCreateValidator : AbstractValidator<ProductCreate>
{
public ProductCreateValidator()
{
RuleFor(product => product.ProductCategory).NotNull();
RuleFor(product => product.ProductName).NotNull();
}
}
And in my controller, I am checking whether my ModelState is valid or not,
[HttpPost]
public ActionResult Create(ProductCreate model)
{
/* This is a method in viewmodel that fills dropdownlists from db */
model.FillDropDownLists();
/* Here this is always valid */
if (ModelState.IsValid)
{
SaveProduct(model);
return RedirectToAction("Index");
}
// If we got this far, something failed, redisplay form
return View(model);
}
This is what I have. My problem is ModelState.IsValid returns true when my viewmodel is completely empty. Do i need to manually configure Fluent validation so that model errors can be added to ModalState ?
As the documentation explains, make sure you have added the following line in your Application_Start in order to swap the data annotations model metadata provider and use fluent validation instead:
FluentValidationModelValidatorProvider.Configure();
Also the following comment in your action scares me:
/* This is a method in viewmodel that fills dropdownlists from db */
model.FillDropDownLists();
A View model shouldn't know what a database means. So having such methods in your view model is a very wrong approach.

ASP.NET MVC 2 validation LINQ to SQL

Currently I have a DataModel object which contains my linq to sql classes(a dmbl file). Currently I use a partial class to validate the incoming input. For example
public partial class User : IEntity
{
public NameValueCollection CheckModel()
{
return GetRuleViolations();
}
/// <summary>
/// Method validates incoming data, by given rules in the if statement.
/// </summary>
/// <returns>NameValueCollection</returns>
private NameValueCollection GetRuleViolations()
{
NameValueCollection errors = new NameValueCollection();
if (string.IsNullOrEmpty(Username))
errors.Add("Username", "A username is required");
// and so on
return errors;
}
}
Now what I want to try to do is add validation attributes to the fields. For example I want to try to add the required attribute to the field Username instead/in addtion of using the validation I currently have. My question is how can I achieve this because the dmbl file is auto generated. Or maybe it is not possible and should I use a different approach?
You should read about Metadata classes. This is example blog entry about it.
Adding Required atrribute to User class will be something like:
[MetadataType(typeof(UserMetadata))]
public partial class User
{
}
public class UserMetadata
{
[Required]
public string Username { get; set; }
}

Model Validation problem in ASP.NEt MVC 2 RC 2

I have facing the following problem after the update.
I have a Model with Class level Validation plus property level validation in it. After updating to MVC 2 RC 2. The model validation fails on Model binding. What i actually understand that new mechanism trying to validate the model when you first request it or say on GET and it get null object exception during tryvalidatemodel Model binding call.
My Model is like this below
[Serializable]
[MetadataType(typeof(InterestClaimMetaData))] //metadata with all properties level validation
//these validations fails when you request a page.
[DateComparison("DateA", "DateB", eDateComparitor.GreaterThan,
ErrorMessage = "Date A must be greater than B Date")]
[MutuallyExclusive("A", "B", ErrorMessage = "Please select either A or B field")]
public class IE {
public int ID { get; set; }
public byte[] Updated { get; set; }
}
DataComparison and MutuallyExclusive overrides the validate function isvalid and check the validation but it fails trying to validate as first requested.
dont know how to stop this happening as it should not validate model on get request; just attach the properties.
Only models without these class level validation works.
Please advise.
Thanks
Seperate your action method in your controller in to two action methods. Mark one as GET and the other as POST. Then only apply the validation in the POST method. So, for example, if you currently have an method called Create that looks something like this...
public ActionResult Create(YourModel yourModel)
{
// Some code in here to validate stuff
// Some code in here to do stuff
return RedirectToAction("Index");
}
Split this out in to two methods like this...
[HttpGet]
public ActionResult Create()
{
return View();
}
[HttpPost]
public ActionResult Create(YourModel yourModel)
{
try
{
// Some code in here to validate stuff
// Some code in here to do stuff
return RedirectToAction("Index");
}
catch
{
return View();
}
}

Resources