This article shows how ASP.NET Core 1.0 localization can be used together with data annotations. The data annotations are used to decorate the data model, and when HTTP POST/PUT (also PATCH) Requests are sent with model errors, the error message is returned localized in the request culture.
Code: https://github.com/damienbod/AspNet5Localization
20.11.2015: Updated to ASP.NET Core 1.0 rc1
Localization Setup
In the Startup class, the AddDataAnnotationsLocalization is added in the ConfigureServices method.
services.AddMvc() .AddViewLocalization() .AddDataAnnotationsLocalization();
Now a model class can be created and the data annotations can be used. The Length property in this example has a range attribute, with an ErrorMessageResourceName and an ErrorMessageResourceType property set. The ErrorMessageResourceType is used to define the resource itself using the type and the ErrorMessageResourceName is used to define the resource identifier. Only the Length property has localized error messages implemented.
using System.ComponentModel.DataAnnotations; using AspNet5Localization.Resources; namespace AspNet5Localization.Model { public class Box { public long Id { get; set; } public double Height { get; set; } public double Width { get; set; } [Required(ErrorMessageResourceName = "BoxLengthRequired", ErrorMessageResourceType = typeof(AmazingResource))] [Range(1.0, 100.0, ErrorMessageResourceName = "BoxLengthRange", ErrorMessageResourceType = typeof(AmazingResource))] public double Length { get; set; } } }
Now a MVC 6 controller can be created which uses the model class. This controller implements POST and PUT action methods, which uses the ModelState to validate the request. If the model is invalid, the error message is returned with a localized value.
using AspNet5Localization.Model; using Microsoft.AspNet.Mvc; namespace AspNet5Localization.Controllers { [Route("api/[controller]")] public class BoxesController : Controller { [HttpGet("{id}")] public IActionResult Get(int id) { if (id == 0) { return HttpNotFound(id); } return Ok(new Box() { Id = id, Height = 10, Length = 10, Width=10 }); } /// <summary> /// http://localhost:5000/api/boxes?culture=it-CH /// Content-Type: application/json /// /// { "Id":7,"Height":10,"Width":10,"Length":1000} /// </summary> /// <param name="box"></param> /// <returns></returns> [HttpPost] public IActionResult Post([FromBody]Box box) { if (!ModelState.IsValid) { return HttpBadRequest(ModelState); } else { string url = Url.RouteUrl("api/boxes", new { id = 11111 }, Request.Scheme, Request.Host.ToUriComponent()); return Created(url, box); } } [HttpPut("{id}")] public IActionResult Put(int id, [FromBody]Box box) { if(id == 0) { return HttpNotFound(box); } if (!ModelState.IsValid) { return HttpBadRequest(ModelState); } else { return Ok(box); } } [HttpDelete("{id}")] public IActionResult Delete(int id) { if (id == 0) { return HttpNotFound(id); } return Ok(); } } }
Now the POST method can be called in Fiddler or Postman. Underneath is an example of a HTTP POST Request using the it-CH culture. The length property is outside the range and will return an model state error.
http://localhost:5000/api/boxes?culture=it-CH User-Agent: Fiddler Host: localhost:5000 Content-Length: 46 Content-Type: application/json { "Id":7,"Height":10,"Width":10,"Length":1000}
HTTP Response with a it-CH localized error message:
HTTP/1.1 400 Bad Request Date: Sat, 24 Oct 2015 17:15:28 GMT Content-Type: application/json; charset=utf-8 Server: Kestrel Transfer-Encoding: chunked {"Length":["The box length should be between 1 and a 100 it-CH"]}
Localization can be used in data annotations like previous versions of MVC or Web API and provides a simple way of validating your data inputs.
Links:
https://github.com/aspnet/Localization
https://github.com/aspnet/Tooling/issues/236
http://www.jerriepelser.com/blog/how-aspnet5-determines-culture-info-for-localization
https://github.com/WeebDo/WeebDo.CMF
https://github.com/joeaudette/cloudscribe
https://github.com/aspnet/Mvc/tree/dev/test/WebSites/LocalizationWebSite
Example of localization middleware for culture in route
http://weblogs.asp.net/jeff/beating-localization-into-submission-on-asp-net-5
