Using DataAnnotations and Localization in ASP.NET Core MVC

This article shows how ASP.NET Core 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.

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 System.Collections.Generic;
using System.Globalization;
using AspNet5Localization.Controllers;
using Microsoft.Extensions.Localization;  
namespace AspNet5Localization.Model
{
    public class Box
    {
        public long Id { get; set;
        public double Height { get; set;
        public double Width { get; set; }
        [Required(ErrorMessage = "BoxLengthRequired")]
        [Range(1.0, 100.0, ErrorMessage = "BoxLengthRange")]
        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.AspNetCore.Mvc;
namespace AspNet5Localization.Controllers
{
    [Route("api/[controller]")]
    public class BoxesController : Controller
    {
        [HttpGet("{id}")]
        public IActionResult Get(int id)
        {
            if (id == 0)
            {
                return NotFound(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 BadRequest(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 NotFound(box);
            }
 
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }
            else
            {
                return Ok(box);
            }
        }
 
        [HttpDelete("{id}")]
        public IActionResult Delete(int id)
        {
            if (id == 0)
            {
                return NotFound(id);
            }
 
            return new NoContentResult();
        }
    }
}

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.

Best ASP.NET Hosting Recommendation

ASPHostPortal.com provides its customers with Plesk Panel, one of the most popular and stable control panels for Windows hosting, as free. You could also see the latest .NET framework, a crazy amount of functionality as well as Large disk space, bandwidth, MSSQL databases and more. All those give people the convenience to build up a powerful site in Windows server. ASPHostPortal.com offers ASP.NET hosting starts from $1/month only. They also guarantees 30 days money back and guarantee 99.9% uptime. If you need a reliable affordable ASP.NET Hosting, ASPHostPortal.com should be your best choice.