Este producto no es compatible con el sitio Datadog seleccionado. ().
Esta página aún no está disponible en español. Estamos trabajando en su traducción. Si tienes alguna pregunta o comentario sobre nuestro actual proyecto de traducción, no dudes en ponerte en contacto con nosotros.
Metadata
ID:csharp-best-practices/use-model-binding
Language: C#
Severity: Notice
Category: Best Practices
Description
This rule encourages developers to use model binding instead of directly accessing data from the request object, such as Request.Form or Request.Headers. Model binding provides a clean and declarative way to receive input data by mapping HTTP request data to strongly typed parameters or models in controller actions.
Using model binding improves code readability, reduces boilerplate parsing and validation logic, and leverages built-in framework features like automatic type conversion and validation attributes. It helps prevent errors related to manual data extraction and parsing, which can introduce bugs or security vulnerabilities if not handled carefully.
To comply with this rule, define a model class representing the expected input and use action method parameters with attributes like [FromForm] or [FromHeader] to bind incoming data automatically. For example, use public IActionResult Register([FromForm] UserRegistrationModel model) instead of manually reading from Request.Form. This approach ensures cleaner, safer, and more maintainable code.
Non-Compliant Code Examples
usingMicrosoft.AspNetCore.Mvc;usingSystem;usingSystem.Collections.Generic;namespaceMyApp.Controllers{publicclassUserController:Controller{ [HttpGet]publicIActionResultRegister(){returnView();}// NON-COMPLIANT: Direct access to Request.Headers [HttpPost]publicIActionResultRegister_NonCompliant(){// Noncompliant: Direct access to Request.Headersvarname=Request.Headers["X-User-Name"].ToString();varemail=Request.Headers["X-User-Email"].ToString();varpassword=Request.Headers["X-User-Password"].ToString();varbirthdateStr=Request.Headers["X-User-Birthdate"].ToString();// Manual parsing and error handlingif(!DateTime.TryParse(birthdateStr,outvarbirthdate)){returnBadRequest("Invalid birthdate");}// Manual validationif(string.IsNullOrEmpty(name)||string.IsNullOrEmpty(email)){returnBadRequest("Name and email are required");}// Process registration...returnOk($"User {name} registered successfully");}// COMPLIANT: Using FromHeader attribute (Recommended) [HttpPost("register-compliant")]publicIActionResultRegister_Compliant( [FromHeader(Name = "X-User-Name")]stringname, [FromHeader(Name = "X-User-Email")]stringemail, [FromHeader(Name = "X-User-Password")]stringpassword, [FromHeader(Name = "X-User-Birthdate")]DateTimebirthdate){// Automatic binding and type conversionif(!ModelState.IsValid){returnBadRequest(ModelState);}// Manual validation (or use Data Annotations)if(string.IsNullOrEmpty(name)||string.IsNullOrEmpty(email)){returnBadRequest("Name and email are required");}// Process registration...returnOk($"User {name} registered successfully");}}}
usingMicrosoft.AspNetCore.Mvc;usingSystem;usingSystem.Collections.Generic;namespaceMyApp.Controllers{publicclassUserController:Controller{ [HttpGet]publicIActionResultRegister(){returnView();} [HttpPost]publicIActionResultRegister_NonCompliant(){// Noncompliant: Direct access to Request.Formvarname=Request.Form["name"];varemail=Request.Form["email"];varpassword=Request.Form["password"];varbirthdateStr=Request.Form["birthdate"];// Manual parsing and error handlingif(!DateTime.TryParse(birthdateStr,outvarbirthdate)){returnBadRequest("Invalid birthdate");}// Manual validationif(string.IsNullOrEmpty(name)||string.IsNullOrEmpty(email)){returnBadRequest("Name and email are required");}// Process registration...returnOk($"User {name} registered successfully");}}}
Compliant Code Examples
usingMicrosoft.AspNetCore.Mvc;usingSystem;usingSystem.ComponentModel.DataAnnotations;namespaceMyApp.Controllers{// Model class for registrationpublicclassUserRegistrationModel{ [Required(ErrorMessage = "Name is required")] [StringLength(100, ErrorMessage = "Name cannot exceed 100 characters")]publicstringName{get;set;} [Required(ErrorMessage = "Email is required")] [EmailAddress(ErrorMessage = "Invalid email format")]publicstringEmail{get;set;} [Required(ErrorMessage = "Password is required")] [MinLength(6, ErrorMessage = "Password must be at least 6 characters")] [DataType(DataType.Password)]publicstringPassword{get;set;} [Required(ErrorMessage = "Birthdate is required")] [DataType(DataType.Date)]publicDateTimeBirthdate{get;set;}}publicclassUserController:Controller{ [HttpGet]publicIActionResultRegister(){returnView();}// COMPLIANT: Using Model Binding with [FromForm] [HttpPost]publicIActionResultRegister([FromForm]UserRegistrationModelmodel){// Automatic validation based on Data Annotationsif(!ModelState.IsValid){returnBadRequest(ModelState);}// Process registration with validated model// All type conversions are handled automatically// birthdate is already a DateTime, not a stringreturnOk($"User {model.Name} registered successfully");}// Alternative: If you want to return validation errors to a view [HttpPost("register-view")]publicIActionResultRegisterWithView([FromForm]UserRegistrationModelmodel){if(!ModelState.IsValid){// Return to view with validation errorsreturnView("Register",model);}// Process registration...TempData["SuccessMessage"]=$"User {model.Name} registered successfully";returnRedirectToAction("Success");}// Alternative: Using individual parameters (less common, but valid) [HttpPost("register-params")]publicIActionResultRegisterWithParameters( [FromForm]stringname, [FromForm]stringemail, [FromForm]stringpassword, [FromForm]DateTimebirthdate){// Manual validation needed with this approachif(string.IsNullOrEmpty(name)||string.IsNullOrEmpty(email)){returnBadRequest("Name and email are required");}if(!ModelState.IsValid){returnBadRequest(ModelState);}// Process registration...returnOk($"User {name} registered successfully");} [HttpGet("success")]publicIActionResultSuccess(){returnView();}}}
Integraciones sin problemas. Prueba Datadog Code Security
Datadog Code Security
Prueba esta regla y analiza tu código con Datadog Code Security
Cómo usar esta regla
1
2
rulesets:- csharp-best-practices # Rules to enforce C# best practices.
Crea un static-analysis.datadog.yml con el contenido anterior en la raíz de tu repositorio
Utiliza nuestros complementos del IDE gratuitos o añade análisis de Code Security a tus pipelines de CI.