Created
March 4, 2013 19:13
-
-
Save raghuramn/5084608 to your computer and use it in GitHub Desktop.
Sample showing how to implement ~/entityset/key/property kind of url support in web API OData. Run and try the url http://localhost:8080/customers(42)/ID or http://localhost:8080/customers(42)/Name for a demo.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Linq; | |
using System.Linq.Expressions; | |
using System.Net; | |
using System.Net.Http; | |
using System.Reflection; | |
using System.ServiceModel; | |
using System.Web.Http; | |
using System.Web.Http.OData; | |
using System.Web.Http.OData.Builder; | |
using System.Web.Http.OData.Formatter; | |
using System.Web.Http.OData.Routing; | |
using System.Web.Http.SelfHost; | |
using Microsoft.Data.Edm; | |
namespace ODataTests | |
{ | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
HttpSelfHostConfiguration config = new HttpSelfHostConfiguration("http://localhost:8080"); | |
config.HostNameComparisonMode = HostNameComparisonMode.Exact; | |
config.Routes.MapODataRoute("default", "", GetEdmModel()); | |
config.Formatters.Clear(); | |
config.Formatters.InsertRange(0, ODataMediaTypeFormatters.Create()); | |
HttpSelfHostServer server = new HttpSelfHostServer(config); | |
server.OpenAsync().Wait(); | |
Console.WriteLine("started.."); | |
Console.ReadKey(); | |
} | |
private static IEdmModel GetEdmModel() | |
{ | |
ODataConventionModelBuilder builder = new ODataConventionModelBuilder(); | |
builder.EntitySet<Customer>("customers"); | |
return builder.GetEdmModel(); | |
} | |
} | |
public class CustomersController : ODataController | |
{ | |
[AcceptVerbs("GET", "POST", "PUT", "POST", "PATCH", "MERGE")] | |
public HttpResponseMessage HandleUnmappedRequest(ODataPath odataPath) | |
{ | |
// Handle property GET. | |
if (Request.Method == HttpMethod.Get && | |
(odataPath.PathTemplate == "~/entityset/key/property" || | |
odataPath.PathTemplate == "~/entityset/key/cast/property")) | |
{ | |
string propertyName = (odataPath.Segments.Last() as PropertyAccessPathSegment).PropertyName; | |
string key = (odataPath.Segments[1] as KeyValuePathSegment).Value; | |
// replace with code to get the entity by key. | |
var customer = new Customer { ID = 42 }; | |
// use reflection to get the property. replace with code specific to your provider. | |
PropertyInfo property = customer.GetType().GetProperty(propertyName); | |
object propertyValue = property.GetValue(customer); | |
// use the custom CreateResponse overload. | |
return Request.CreateResponse(HttpStatusCode.OK, property.PropertyType, propertyValue); | |
} | |
throw new HttpResponseException(HttpStatusCode.BadRequest); | |
} | |
} | |
public static class HttpRequestMessageExtensions | |
{ | |
private static MethodInfo _createResponse = InitCreateResponse(); | |
private static MethodInfo InitCreateResponse() | |
{ | |
Expression<Func<HttpRequestMessage, HttpResponseMessage>> expr = | |
(request) => request.CreateResponse<object>(HttpStatusCode.OK, default(object)); | |
return (expr.Body as MethodCallExpression).Method.GetGenericMethodDefinition(); | |
} | |
// Content negotiation doesn't use the runtime type of the object. This helper method is CreateResponse overload that passes | |
// the specified type to content negotiation. | |
public static HttpResponseMessage CreateResponse(this HttpRequestMessage request, HttpStatusCode status, Type type, object value) | |
{ | |
return _createResponse.MakeGenericMethod(type).Invoke(null, new[] { request, status, value }) as HttpResponseMessage; | |
} | |
} | |
public class Customer | |
{ | |
public int ID { get; set; } | |
public string Name { get; set; } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment