开发者

(Multi-Tenant WCF Services) Parameter less methods with URL routing for WCF

开发者 https://www.devze.com 2023-03-23 13:15 出处:网络
This is related question to my previous question but different one. After searching a lot I’m not able to find the best solution for following WCF problem.

This is related question to my previous question but different one.

After searching a lot I’m not able to find the best solution for following WCF problem.

There is just one SVC file but multiple URLs to access it e.g. Organization Org1 will have URL http://CRMserver_name/Org1/XRMServices/2011/Organization.svc and Org2 will have http://CRMserver_name/Org2/XRMServices/2011/Organization.svc

I was trying this using URL Routing but problem is, it is creating REST services which we don’t want. We should be able to access these services just like normal WCF service. So if we add the URL http://CRMserver_name/Org1/XRMServices/2011/Organization.svc in WCF test client it should work.

CRM is doing it so there is a way but I’m not able 开发者_运维百科to find it. Help me out!

Thanks, Nilesh


I am not sure whether this would solve your problem, but do have a look at the IIS Url Rewrite module. It may solve your problem.


After lot of research I’m going with safe way to achieve this. I’m going create separate WCF projects for each tenant and host them in separate IIS virtual dirs. e.g. For Tenant1 - http://localhost/ Tenant1/Service1.svc and for Tenant2 - http://localhost/Tenant2/Service1.svc Note that SVC name is same. Then I'm removing IService1.cs and Service1.svc.cs from Tenant2 and adding existing file as link from Tenant1. I need to do this for each new tenant and that's why this is not pure solution. Now my solution explorer looks like following.

(Multi-Tenant WCF Services) Parameter less methods with URL routing for WCF

Here WcfService3 is for Tenant1 and WcfService1 is for Tenant2 (Sorry for this confusing names. I might fix it if someone need). So my WcfService3 properties look like following.

(Multi-Tenant WCF Services) Parameter less methods with URL routing for WCF

Now for both http://localhost/ Tenant1/Service1.svc and http://localhost/ Tenant2/Service1.svc service code is at single place which is in WcfServices3->Service1.svc.cs. Following code will create the database connection object for specific method call.

    private static string dbServerName = "YourDBServerName";    
    private static SqlConnection dbConnection = createDBConnection();            
    private static SqlConnection createDBConnection()
    {
        Uri fullUri = OperationContext.Current.IncomingMessageHeaders.To;
        Uri baseAddress = new Uri(@"http://localhost");
        UriTemplate template = new UriTemplate(@"/{orgName}/Service1.svc");

        // retrieve the value of the artist segment
        UriTemplateMatch match = template.Match(baseAddress, fullUri);
        String orgName = match.BoundVariables["orgName"];        

        SqlConnection objConnection = new SqlConnection();
        objConnection.ConnectionString = createConnString(orgName);

        return objConnection;
    }

    private static string createConnString(string orgName)
    {
        return (String.Format("Data Source={0};Initial Catalog={1}_MSCRM;User Id=UserId1;Password=PasswordForUserId1;", dbServerName, orgName));
    }

I know this is not real solution for the problem (Multi-Tenant WCF services) but quick, easy and safe work around. Hope this helps someone. Also if you see any issues here or know better solution please let me know.

-Nilesh


I've found what I think is a better approach. Rather than trying to pick up the target Uri from the IncomingMessageHeaders object (which gives you the server's view of the host, not the client's), pick it up from the HttpRequest headers instead.

Here are a couple of service methods I have created that prove this in two ways:

  1. GetTenantByRewrittenURL works in conjunction with a URL Rewrite 2.0 rule. This rule will find the tenant name in the first part of the Uri path (after the domain), e.g. www.mydomain.com/tenant1/MyService.svc. It then (a) rewrites the URL, stripping out the tenant ID, and (b) stores the tenant ID in the HTTP_REFERER header field. I can give you the URL Rewrite rule to do this if you are unsure; don't forget to also add HTTP_REFERER to the list of accepted server variables in the URL Rewrite config.

  2. GetTenantByFakeHost works in conjunction with host headers. For this, I've added a host header to my IIS bindings to expect requests in the form tenant1.mydomain.com/MyService.svc

This appears to achieve what you were aiming for, and hopefully you should be able to access the Http headers throughout your middle tier via the OperationContext, though I have not yet verified that.

   public string GetTenantIDByRewrittenURL()
    {
        HttpRequestMessageProperty prop = (HttpRequestMessageProperty) OperationContext.Current.IncomingMessageProperties[HttpRequestMessageProperty.Name];
        string tenantID = prop.Headers[HttpRequestHeader.Referer];

        return tenantID;
    }

    public string GetTenantIDByFakeHost()
    {
        HttpRequestMessageProperty prop = (HttpRequestMessageProperty)OperationContext.Current.IncomingMessageProperties[HttpRequestMessageProperty.Name];
        string tenantID = prop.Headers[HttpRequestHeader.Host];

        return tenantID;
    }
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号