Is there a way to return custom response through conneg?

Topics: Web Api
Jan 25, 2012 at 12:00 AM

I want to write a message handler that will return the content translated by the built-in conneg system.

I want it to still use my request and response handlers, because they change the way I handle the conneg rules (by adding defaults, removing types, etc).

My end goal:

To have a message handler that takes requests at /authtoken that takes 2 querystring parameters username and password, and returns the login token with an expiration date.

If they are sending/requesting JSON, I want to send back JSON. If they are requesting/sending JSONP I want to return JSONP. If they are requesting/sending XML I want to return XML.

I have no idea how to handle this inside a message handler without doing all the work manually.

Jan 25, 2012 at 12:03 AM

When I say I want all the same handlers, I should say that I basically just want to replace the "service" part of the call. All the rest of the handlers I want to execute like normal.

If I cannot do this, then I guess I can just make a service that handles it, but I would rather abstract it out into the handler so that we don't have a service for token distribution and that it can be requested at any url.

if (request.RequestUri.Segments.Last() == "authtoken")

Jan 25, 2012 at 12:10 AM

This is what I have so far:

    public class TokenAuthenticationMessageHandler : DelegatingHandler
    {
        protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            if (request.RequestUri.Segments.Last() == "authtoken")
            {
                return Task.Factory.StartNew(() =>
                {
                    string userName = request.QueryString("username");
                    string password = request.QueryString("password");

                    string token, content;
                    JsonObject contentObject;

                    var service = UserTokenService.Instance;
                    if (!service.ValidateUser(userName, password, out token))
                    {
                        contentObject = new JsonObject()
                        {
                            { "errorMessage", "Invalid username and password combination." },
                            { "success", "false" }
                        };
                    }
                    else
                    {
                        contentObject = new JsonObject()
                        {
                            { "authToken", token },
                            { "expiresOn", "never" }
                        };
                    }

                    if (!string.IsNullOrEmpty(request.QueryString("callback")))
                        content = String.Format("{0}({1})", request.QueryString("callback"), contentObject);
                    else
                        content = contentObject.ToString();

                    var response = new HttpResponseMessage();
                    response.Content = new StringContent(content);
                    response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                    response.Headers.CacheControl = new CacheControlHeaderValue() { NoCache = true };

                    return response;
                });
            }

            return base.SendAsync(request, cancellationToken);
        }
    }