Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In ASP.NET WebApi, why is RouteData's value type "object" and not "string"

In WebApi, RouteData has a Values property which is where route data is stored. For some reason, however, it implements IDictionary<string, object> rather than IDictionary<string, string>. Is the value type ever not going to be a string?

The context is that I'm writing a custom IHttpRouteConstraint to check if an integer is inside a specified range. In order to do this, I must cast my value to string and then use int.TryParse. But this will fail if the value is actually an int. Can this ever happen?

like image 404
coppro Avatar asked Jan 18 '26 11:01

coppro


1 Answers

If you see the source code ,you'll notice Unit Tests where the value is not a string(for example BindValuesAsync_RouteData_Values_To_Simple_Types).

You said you are writing a custom constraint,let's take this one:

 public class MyConstraint : IHttpRouteConstraint
 {
       public bool Match(HttpRequestMessage request, IHttpRoute route, string parameterName, IDictionary<string, object> values, HttpRouteDirection routeDirection)
       {
            string parameters = string.Join(Environment.NewLine, values.Select(p => p.Value.GetType().FullName).ToArray());
            return true;
       }
  } 

You register it:

 config.Routes.MapHttpRoute("DefaultApi",
                                   "api/{controller}/{action}/{id}",
                                   new { id = RouteParameter.Optional }, 
                                   new { isLocal = new MyConstraint() });

Assuming you have this controller:

public class ValuesController : ApiController
{
    public string Get(int id) { return "Value"; }
}

If you make a GET request to "/api/values/Get/1" you'll notice the the values are of type

  • System.String //values
  • System.String //Get
  • System.String //1

But

If you make a GET request to "/api/values/1" you'll notice the the values are of type

  • System.String //values
  • System.String //1
  • System.Web.Http.RouteParameter

If you see the source code of the class

/// <summary>
/// The <see cref="RouteParameter"/> class can be used to indicate properties about a route parameter (the literals and placeholders 
/// located within segments of a <see cref="M:IHttpRoute.RouteTemplate"/>). 
/// It can for example be used to indicate that a route parameter is optional.
/// </summary>
public sealed class RouteParameter
{
    public static readonly RouteParameter Optional = new RouteParameter();

    // singleton constructor
    private RouteParameter()        {   }

    public override string ToString()   {  return string.Empty;      }
}

So, one occasion this is not a string is when you don't provide optional arguments.
You should first check the type of the object and only if it is a non empty string,try to parse it

like image 191
George Vovos Avatar answered Jan 21 '26 01:01

George Vovos



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!