locked
Custom routing in data services RRS feed

  • Question

  • I need to create a custom route for a WCF data service that contains a segment that must be extracted for use in filtering data.

    Example:

    http://mysample.net/mysamplesvc/client123/Users

    I need to extract the client123 from the route. It looks like the Route class might provide something similar but I am not sure how to implement an IRouteHandler for a Data service.

    Is this the correct path? Are there good examples around?

    TIA!

    Friday, December 9, 2011 6:01 PM

Answers

  • Ok, I think I may have come up with a solution thanks to some guidance by an SO user. I have implemented the following code in the

            public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel, InstanceContext instanceContext)
            {
                HttpRequestMessageProperty httpmsg = (HttpRequestMessageProperty)request.Properties[HttpRequestMessageProperty.Name];
                ...Additional logic for handling Query formats in OData
    			
    			
                UriTemplate template = new UriTemplate("mysamplesvc/{ClientId}", true);
    
                Uri prefix = new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Authority));
                Uri uri = new Uri(HttpContext.Current.Request.Url.AbsoluteUri);
                UriTemplateMatch results = template.Match(prefix, uri);
                
                if (results != null && !string.IsNullOrEmpty(results.BoundVariables["ClientId"]))
                {
                    _clientId = results.BoundVariables["ClientId"].ToString();
                }
    
                if (!string.IsNullOrEmpty(_clientId))
                {
                    httpmsg.Headers.Add("ClientId", _clientId);
                    rewriteRequest();
                }
                return null;
            }
    
            private void rewriteRequest()
            {
                if (HttpContext.Current != null && HttpContext.Current.Session != null)
                {
                    if (WebOperationContext.Current.IncomingRequest.UriTemplateMatch != null)
                    {
                        Uri serviceUri = HttpContext.Current.Session["ServiceUri"] as Uri;
                        Uri requestUri = null;
    
                        UriTemplateMatch match = WebOperationContext.Current.IncomingRequest.UriTemplateMatch;
    
                        if (serviceUri == null)
                        {
                            UriBuilder serviceUriBuilder = new UriBuilder(match.BaseUri);
    
                            serviceUri = serviceUriBuilder.Uri;
                            HttpContext.Current.Session["ServiceUri"] = serviceUri;
                        }
    
                        if (serviceUri != null)
                        {
                            OperationContext.Current.IncomingMessageProperties["MicrosoftDataServicesRootUri"] = serviceUri;
    
                            UriBuilder requestUriBuilder = new UriBuilder(match.RequestUri);
                            string path = string.Empty;
                            if (match.RelativePathSegments[0] == _clientId)
                            {
                                foreach (var seg in match.RelativePathSegments.Select((x, i) => new { Value = x, Index = i }))
                                {
                                    if (seg.Index != 0)
                                    {
                                        path += "/";
                                        path += seg.Value;
                                    }
                                }
                            }
                            else
                            {
                                foreach (var seg in match.RelativePathSegments.Select((x, i) => new { Value = x, Index = i }))
                                {
                                    path += "/";
                                    path += seg.Value;
                                }
                            }
    
                            UriBuilder serviceUriBuilder = new UriBuilder(match.BaseUri + path);
    						
                            // because we have overwritten the Root URI, we need to make sure the request URI shares the same host
                            // (sometimes we have request URI resolving to a different host, if there are firewall re-directs
                            serviceUriBuilder.Host = serviceUri.Host;
    
                            requestUri = serviceUriBuilder.Uri;
                            OperationContext.Current.IncomingMessageProperties["MicrosoftDataServicesRequestUri"] = requestUri;
                            OperationContext.Current.IncomingMessageProperties["Via"] = requestUri;
                        }
                    }
    
                }
            }
    


    I was hoping that if somebody more failiar with this re-writing via the OperationContext read this they could tell me where I went wrong. I'm sure I did.

     

    Thanks.

    • Marked as answer by rkbrown Tuesday, December 13, 2011 5:26 PM
    Monday, December 12, 2011 10:20 PM

All replies

  • Could somebody please respond to this? I am in a predicament and need an answer as to whether this is possible or not. any response would be appreciated.

     

    thanks.

    Monday, December 12, 2011 4:14 PM
  • Ok, I think I may have come up with a solution thanks to some guidance by an SO user. I have implemented the following code in the

            public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel, InstanceContext instanceContext)
            {
                HttpRequestMessageProperty httpmsg = (HttpRequestMessageProperty)request.Properties[HttpRequestMessageProperty.Name];
                ...Additional logic for handling Query formats in OData
    			
    			
                UriTemplate template = new UriTemplate("mysamplesvc/{ClientId}", true);
    
                Uri prefix = new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Authority));
                Uri uri = new Uri(HttpContext.Current.Request.Url.AbsoluteUri);
                UriTemplateMatch results = template.Match(prefix, uri);
                
                if (results != null && !string.IsNullOrEmpty(results.BoundVariables["ClientId"]))
                {
                    _clientId = results.BoundVariables["ClientId"].ToString();
                }
    
                if (!string.IsNullOrEmpty(_clientId))
                {
                    httpmsg.Headers.Add("ClientId", _clientId);
                    rewriteRequest();
                }
                return null;
            }
    
            private void rewriteRequest()
            {
                if (HttpContext.Current != null && HttpContext.Current.Session != null)
                {
                    if (WebOperationContext.Current.IncomingRequest.UriTemplateMatch != null)
                    {
                        Uri serviceUri = HttpContext.Current.Session["ServiceUri"] as Uri;
                        Uri requestUri = null;
    
                        UriTemplateMatch match = WebOperationContext.Current.IncomingRequest.UriTemplateMatch;
    
                        if (serviceUri == null)
                        {
                            UriBuilder serviceUriBuilder = new UriBuilder(match.BaseUri);
    
                            serviceUri = serviceUriBuilder.Uri;
                            HttpContext.Current.Session["ServiceUri"] = serviceUri;
                        }
    
                        if (serviceUri != null)
                        {
                            OperationContext.Current.IncomingMessageProperties["MicrosoftDataServicesRootUri"] = serviceUri;
    
                            UriBuilder requestUriBuilder = new UriBuilder(match.RequestUri);
                            string path = string.Empty;
                            if (match.RelativePathSegments[0] == _clientId)
                            {
                                foreach (var seg in match.RelativePathSegments.Select((x, i) => new { Value = x, Index = i }))
                                {
                                    if (seg.Index != 0)
                                    {
                                        path += "/";
                                        path += seg.Value;
                                    }
                                }
                            }
                            else
                            {
                                foreach (var seg in match.RelativePathSegments.Select((x, i) => new { Value = x, Index = i }))
                                {
                                    path += "/";
                                    path += seg.Value;
                                }
                            }
    
                            UriBuilder serviceUriBuilder = new UriBuilder(match.BaseUri + path);
    						
                            // because we have overwritten the Root URI, we need to make sure the request URI shares the same host
                            // (sometimes we have request URI resolving to a different host, if there are firewall re-directs
                            serviceUriBuilder.Host = serviceUri.Host;
    
                            requestUri = serviceUriBuilder.Uri;
                            OperationContext.Current.IncomingMessageProperties["MicrosoftDataServicesRequestUri"] = requestUri;
                            OperationContext.Current.IncomingMessageProperties["Via"] = requestUri;
                        }
                    }
    
                }
            }
    


    I was hoping that if somebody more failiar with this re-writing via the OperationContext read this they could tell me where I went wrong. I'm sure I did.

     

    Thanks.

    • Marked as answer by rkbrown Tuesday, December 13, 2011 5:26 PM
    Monday, December 12, 2011 10:20 PM
  • Hi rkbrown,

    Thanks for sharing your experience here.

    Have a nice day.


    Alan Chen[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Wednesday, December 14, 2011 6:59 AM
    Moderator