Search code examples
asp.netsilverlightwcf-ria-servicessilverlight-5.0ria

How to pass connection string name from Silverlight Application to DomainService


First I want to say I'm not SL developer. I just need to modify one legacy Silverlight 5 application.

It is using RIA services and XAP is hosted in Asp.Net page.

User on login page enters credentials and is able to select database from dropdown. Whole web is using multiple connections and user is able to select database to connect.

This selected database (or any identificator for data connection) is sent do XAP's InitParams, so I can access it from SL.

    private void Application_Startup(object sender, StartupEventArgs e)
    {
        foreach (var item in e.InitParams)
        {
            Resources.Add(item.Key, item.Value);
        }

        var selectedConnectionString = GetInitParam("ConnectionString");

        // TODO: Different way to store connection string
        SetCookie("ConnectionString", selectedConnectionString);

        RootVisual = new LoadingPage();
    }

Currently I'm trying to use cookie to store selected database. I found it somewhere as one possible solution. But it needs to change.

Ok, then we have DomainService.

public class CommissionDomainService : LinqToEntitiesDomainService<CommissionEntitiesContext>
{
    ...
}

I know that I need to use CreateObjectContext to change ConnectionString in service. So I have:

    protected override CommissionEntitiesContext CreateObjectContext()
    {
        // TODO: Different way to store connection string
        string connectionStringName;
        if (System.Web.HttpContext.Current.Request.Cookies["ConnectionString"] != null)
        {
            connectionStringName = System.Web.HttpContext.Current.Request.Cookies["ConnectionString"].Value;
        }
        else
        {
            throw new Exception("Missing connectionStringName");
        }

        var connectionStringSettings = ConfigurationManager.ConnectionStrings[connectionStringName];

        var entityCs = new EntityConnectionStringBuilder
        {
            Metadata = "res://*/CommissionEntities.csdl|res://*/CommissionEntities.ssdl|res://*/CommissionEntities.msl",
            Provider = connectionStringSettings.ProviderName,
            ProviderConnectionString = connectionStringSettings.ConnectionString
        };

        return new CommissionEntitiesContext(entityCs.ConnectionString);
    }

Again, I used Cookie to pass value from application to service.

But it is not the best idea. Because of cookie and because of persistance etc.

My question is, how to pass my ConnectionString value from main application to DomainService? Or Can I access some application context from service? Or maybe can I get connection string somewhere in EntitiesContext?


Solution

  • Ok, I did it this way.

    I made selected database part of user identity. Because I'm using Owin, I just used one of Claims.

    So when user logs in, I just put one claim with selected database

                // build a list of claims
                var claims = new List<Claim>
                {
                    new Claim(ClaimTypes.Name, user.Name),
                    new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
                    new Claim(ClaimTypes.UserData, selectedDatabase)
                };
    
                // create the identity
                var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationType);
    
                // sign in
                Context.GetOwinContext().Authentication.SignIn(new AuthenticationProperties { IsPersistent = false }, identity);
    

    Then in DomainService I used Initialize and CreateObjectContext methods

        private string _connectionStringName;
    
        public override void Initialize(DomainServiceContext context)
        {
            // Načteme z kontextu usera zvolenou databázi
            var claim = ((ClaimsIdentity)context.User.Identity).FindFirst(ClaimTypes.UserData);
            _connectionStringName = claim.Value;
    
            base.Initialize(context);
    
            ...
        }
    
    
        protected override CommissionEntitiesContext CreateObjectContext()
        {
            if (string.IsNullOrEmpty(_connectionStringName))
            {
                throw new Exception("Missing connectionStringName");
            }
    
            var connectionStringSettings = ConfigurationManager.ConnectionStrings[_connectionStringName];
    
            var entityCs = new EntityConnectionStringBuilder
            {
                Metadata = "res://*/CommissionEntities.csdl|res://*/CommissionEntities.ssdl|res://*/CommissionEntities.msl",
                Provider = connectionStringSettings.ProviderName,
                ProviderConnectionString = connectionStringSettings.ConnectionString
            };
    
            return new CommissionEntitiesContext(entityCs.ConnectionString);
        }