2

Suppose you send a class-instance to controller and the class has a property of Enum type.

public class CoffeeController : ApiController
{
    [HttpPost]
    public async Task<IHttpActionResult> OrderAsync(Order request)
    {
        return Ok();
    }
}

public enum CoffeeType
{
    Latte,
    Mocha,
    Espresso
}

public class Order
{
    public CoffeeType Type { get; set; }
    public string Name { get; set; }
}

If there is an error in the name of enum member in request the application doesn't throw exception. It uses a default enum value instead:

{"name":"Dan", 'type':"ocha"}=>{"Name":"Dan", "Type":"Latte"}

This seems odd to me. Why such a behaviour is used?

Is there an elegant way to throw error?

3 Answers 3

1

It does this because Enums are based on an integer type , so they will always have a value (value types cannot be null) and will default to 0. Use following workaround

public enum CoffeeType
{
    Invalid = 0
    Latte = 1,
    Mocha = 2,
    Espresso = 3
}
Sign up to request clarification or add additional context in comments.

Comments

1

Apply validation to your models. Create an ActionFilterAttribute and wire it into your pipeline or decorate your endpoint with it. Recommend you also consider FluentValidation as a great library to perform validation.

See ValidateModelStateFilter example in this article for a great example.

Comments

0

As Brett writed you can use ModelState.IsValid and ModelState will have error. if you need just throw an error you can use custom media formatter for your type, like:

public class OrderJsonFormatter : BufferedMediaTypeFormatter
    {
        public OrderJsonFormatter()
        {
            SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json"));
        }

        public override bool CanReadType(Type type)
        {
            var canRead = type == typeof(Order);
            return canRead;
        }

        public override bool CanWriteType(Type type)
        {
            return false;
        }

        public override object ReadFromStream(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
        {
            return this.ReadFromStream(type, readStream, content, formatterLogger, CancellationToken.None);
        }

        public override object ReadFromStream(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger, CancellationToken cancellationToken)
        {
            using (var reader = new StreamReader(readStream))
            {
                using (var jsonReader = new JsonTextReader(reader))
                {
                    var jsonSerializer = new JsonSerializer();

                    if (type == typeof(Order))
                    {


                        try
                        {
                            var entity = jsonSerializer.Deserialize<Order>(jsonReader);
                            return entity;
                        }
                        catch (Exception ex)
                        {
                         //log error here
                            throw;
                        }
                    }

                    return null;
                }
            }
        }


    }

and register it :

 GlobalConfiguration.Configuration.Formatters.Insert(0, new OrderJsonFormatter());

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.