2

My routing is:

public void RegisterRoute(HttpRouteCollection routes) {
    routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "api/{controller}/{guid}",
        defaults: new { guid = RouteParameter.Optional }
    );
}

controller action is like

public IHttpActionResult Get(Guid guid) {

When I pass api/{controller}/2ADEA345-7F7A-4313-87AE-F05E8B2DE678 everything works fine but when I pass invalid value for guid like

api/{controller}/xxxxxx then I get error :

{
  "message": "The request is invalid.",
  "messageDetail": "The parameters dictionary contains a null entry for parameter 'guid' of non-nullable type 'System.Guid' for method 'System.Web.Http.IHttpActionResult Get(System.Guid)' in 'Web.API.Controller.UserController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter."
}

How can I display my own message like:

{
  "guid": "The value is invalid.",
}

I'm trying to create custom model binder but it is not working

public class GuidModelBinder : IModelBinder {

        public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext) {
            var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
            if (value == null) {
                bindingContext.ModelState.AddModelError("guid", "The value is invalid");
                return false;
            }


            var result = Guid.TryParse(value.ToString(), out _);
            if (!result) {
                bindingContext.ModelState.AddModelError("guid", "The value is invalid");
            }
            return result;
        }
    }

Please help. How can I show only my message

Magnus
  • 45,362
  • 8
  • 80
  • 118
Pr.Dumbledor
  • 636
  • 1
  • 11
  • 29
  • 2
    Whats wrong with the standard error message? Seems pretty clear. – Magnus Jun 26 '17 at 15:10
  • You could do something like this https://stackoverflow.com/questions/7563675/differentiate-guid-and-string-parameters-in-mvc-3 – Qpirate Jun 26 '17 at 15:11
  • @Magnus There are too many information about controller, type ect. I want to show simpler message to the client – Pr.Dumbledor Jun 26 '17 at 15:11
  • Please check this link.It may help you out [https://stackoverflow.com/questions/31577758/web-api-routes-to-support-both-guid-and-integer-ids](https://stackoverflow.com/questions/31577758/web-api-routes-to-support-both-guid-and-integer-ids) – Santhosh kumar Vadlamani Jun 26 '17 at 15:22
  • Please check this link. It may help you out. [enter link description here](https://stackoverflow.com/questions/31577758/web-api-routes-to-support-both-guid-and-integer-ids) – Santhosh kumar Vadlamani Jun 26 '17 at 15:24
  • @SanthoshkumarVadlamani thanks but it doesn't help – Pr.Dumbledor Jun 26 '17 at 15:39

2 Answers2

4

You can do it by making your Guid a Nullable<Guid> and do a null check:

public IHttpActionResult Get(Guid? guid) {

    if(!guid.HasValue || guid.Value == Guid.Empty)
        // return your error here

    else
    //...
}
Grax32
  • 3,986
  • 1
  • 17
  • 32
Maximilian Ast
  • 3,369
  • 12
  • 36
  • 47
1

Close but BindModel must return a Guid. Since your parameter is a guid, which is a value type, it MUST have a non-null value. In the example below, I used Guid.Empty as the value if the passed-in value is not a parsable guid.

This will allow IIS to call your controller with the Guid.Empty value and the Model error you specified.

public class GuidModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        Guid guidValue;
        if (value == null || !Guid.TryParse(value.AttemptedValue, out guidValue))
        {
            bindingContext.ModelState.AddModelError("guid", "The value is invalid");
            return Guid.Empty;
        }

        return guidValue;
    }
}
Grax32
  • 3,986
  • 1
  • 17
  • 32