I am new to MVC 3 and went through lots of cool tutorials. Loving the design pattern and enjoying the productivity boost.
One of the problems I am now having is that I was using the built in database to handle the login that is behind many of the basic MVC apps in most tutorials. I now need to change to access the login details of a live production system this but cant find where to do it.
I initially taught is would be as simple as changing the connection string, but the production database is totally different than the made up example.
It is not obvious to me where the model / controller is getting the data from. For example, where does the model / controller retreive the user name or compair the password. If I knew this then I could alter my solution to point to the correct database / tables / fields.
Also, my real database is modelled in EF and is in a separate project within the same solution. So I have MyProject.Data and MyProject.Web and eventually will have MyProject.Test ect.
Any help here would be greatly appreicated. Thanks in advance.
EDIT 1: The real database also has a login table with user name and password fields, just like the MVC simple login db. However the database is obviously not part of the system like in the sample projects. Instead it is sitting on the server waiting to be accessed.
My problem is that I dont know where to go to make the changes needed. I was thinking it would be the connection string but this is not working. Even the errors I get just point me back to the connection string as opposed to giving me a line of code to find.
The framework pulls the connection string that is named the same as the DbContext derived class by default. So look for a connection string that is the same as this class. Having said that this connection string has absolutely nothing to do with the default forms implementation as that pulls from connection string that is identified in the membership section of the web.config. This should look something like this:
<membership>
<providers>
<clear/>
<add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider" connectionStringName="ApplicationServices"
enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false"
maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10"
applicationName="/" />
</providers>
</membership>
in there you see the connectionStringName identified. You can of course simply change this, but most likely if you already have an existing database, this will most likely not be structured correctly.
The comment by Henk is most likely right in that you will want to create your own membership provider (simply create a class and inherit from MembershipProvider and implement CreateUser, GetUser, ValidateUser, and ApplicationName (or so I think)). You need to make sure to register this provider in place of the AspNetMembershipProvider. Once you do that you should see breakpoints be hit on your provider and simply implement as you need it for your database/AD/...
Related
I am developing a large MVC Web Application with ASP .NET.
I make it as Database First, not Code First.
By creating the Web App with Individual User Accounts Authentication it creates the models, views, controllers and the database for it, which is pretty nice
But I want to change the migration to use my hosted database in the cloud. I tried to change [base("DefaultConnection",...)] in the IdentityModel.cs to use the hosted database, and I also tried to make changes on the Web.config
It was not a good idea! :D
Please, help me!
You just need to search for the "DefaultConnection" ConnectionString in your Web.config file, replace it with your remote server's information and that should be enough to connect to your hosted database.
It should look like this:
<add name="DefaultConnection" connectionString="data source=**YourServer**;initial catalog=**YourDatabaseName**;user id=**DatabaseUsername**;password=**DatabasePassword**" providerName="System.Data.SqlClient" />
I working on a project like you do. I'm using Database First Approach. After create a project with Individual User Authentication, you need to transfer these user tables to your database. You can do this with schema compare.
On the SQL Server Object Explorer > find your localdb that contain user tables > right click > Schema Compare
schema compare
Then select target (your database) and click Compare on right corner.
Select table(s) you want to transfer to your database.
After doing this edit Web.config file:
<add name="DefaultConnection" connectionString="Data Source=YourServerName;Initial Catalog=YourDatabaseName;Integrated Security=True" providerName="System.Data.SqlClient" />
(This connectionString is to use default model, controllers and actions provided by project. If you want to create your own functions for user operations you only need to add below line after transfer tables.)
Here, provider name is important. Don't chance it. This connection string is for user operations.
Then add ADO.NET Entity Data Model to use your other tables with Entity framework
<add name="YourEntityName" connectionString="metadata=res://*/Models.Model1.csdl|res://*/Models.Model1.ssdl|res://*/Models.Model1.msl;provider=System.Data.SqlClient;provider connection string="data source=YourServerNameL;initial catalog=YourDBName;integrated security=True;multipleactiveresultsets=True;application name=EntityFramework"" providerName="System.Data.EntityClient" />
providerName is important here as well.
I add my ado.net in (model folder)
on the web.config change my new connection string to "DefaultConnection"
in the Dbcontext "my ado.net" change to : base("DefaultConnection")
I am currently working on a Sitecore project where the same sitecore webapplication would point to Sitecore databases based on witch IIS website name the webapplication is running under.
Let’s say the IIS webapplication is called www.company1.com, then the database names would be: www.company1.com.master, www.company1.com.web in \App_Config\ConnectionStrings.config.
I have tried to modify the connection string on Application_Start(), but that is not the best solution (possible but slow and ugly, first request dropped etc.).
Another approach is to use config file transformations, but that is not an options based on the number of web sites.
Is it possible to modify Sitecore.Context, somewhere in Application_Start – so Sitecore.Context.Database would work as expected?
You could setup multiple connection strings entries and then reference it in the node in your web.config.
<connectionStrings>
<add name="core" connectionString="[connection_string]" />
<add name="master" connectionString="[connection_string]" />
<add name="web" connectionString="[connection_string]" />
<add name="web1" connectionString="[connection_string]" />
<add name="web2" connectionString="[connection_string]" />
</connectionStrings>
<sites>
<site name="website1" database="web1" hostName="www.company1.com" (...) />
<site name="website2" database="web2" hostName="www.company2.com" (...) />
</sites>
Would that work for you?
I don't think there is. But you would not want to change the actual name of the connection string, you would want to change the value produced by it. Changing the standard Sitecore connection string names ("master", "core" and "web") would require a lot of related changes in web.config and related config files. On top of that you would probably end up in trouble, as there are modules and code out there still - doing specific Factory.GetDatabase("master") API calls - even if they shouldn't.
I've never attempted what you're asking for here in a Sitecore solution, but I expect it should be possible to create your own ConnectionStringProvider, as described in http://msdn.microsoft.com/en-us/library/vstudio/ms254494(v=vs.100).aspx
The provider would need to return proper results for "master", "core" and so on - any databases you would normally have defined in your solution - and then a dynamic connection string based on the pattern you describe; considering the IIS application name or whatever you need.
In my web.config file I have two SQL Server connection strings, one for local and one for live:
<connectionStrings>
<remove name="LocalSqlServer" />
<add name="LocalSqlServer" connectionString="[removed]" providerName="System.Data.SqlClient"/>
<add name="LiveSqlServer" connectionString="[removed]" providerName="System.Data.SqlClient"/>
</connectionStrings>
I then have a "utils" singleton class which basically sets the connection string depending if I'm running the site on "localhost" or on my live server:
if (Environment.MachineName.ToUpper() == MyOwnConfig.GetAppSettingsValue(ConfigKeys.localhost).ToUpper()) {
this.ConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["LocalSqlServer"].ToString();
//MembershipProvider provider = Membership.Providers["LocalAspNetMemberSqlProvider"];
//RoleProvider role = Roles.Providers["LocalAspNetMemberSqlProvider"];
}
else {
this.ConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["LiveSqlServer"].ToString();
//MembershipProvider provider = Membership.Providers["LiveAspNetMemberSqlProvider"];
//RoleProvider role = Roles.Providers["LiveAspNetMemberSqlProvider"];
}
My Database class then simply uses the connectionString property of my utils class. All this works fine so when I place the site locally I can then simply upload it to live without making changes to the connection strings etc in the config file and it starts using my live database.
Now I'm currently implementing "membership" into my site and for ajax for use some webmethods I'm storing the providerUserKey in a text field of the current logged in user. my web method then checks that this key is authenticated. e.g.
ajaxCreds.ajaxID1 = ((MembershipUser)Membership.GetUser()).ProviderUserKey.ToString();
QUESTION:
the question I have is How do I know if this membership is from the LIVE database or my LOCAL database. As you can see from the web config I've added in the membership/provider lines (commented out) but I don't know how to use them with the above membership.getUser() command.
Alternative... Is this a good way to go? or is it simpler to edit the web.config file when I upload to live?
Many thanks
Most people don't do it this way though I applaud you for figuring all this out. Typically, people use the deployment manager or some other build system to have a different web.config value on the server verses local.
Here is a link on changing in deployment: How do I use Web.Config transform on my connection strings?
I would suggest you to read this article:
http://blogs.msdn.com/b/schlepticons/archive/2010/07/22/modifying-asp-net-providers-at-runtime.aspx
It will show you, that also others were trying to do the similar. And this is how to succeed. Solution (if adjusted) could be similar to your needs.
put all the providers into your web.config
On App_Start adjust which will be the default (based on the Environment)
Membership API will be available as you need for Provider Key
No need to search for Provider by Name
NOTE: you have to tweak the void Application_Start(object sender, EventArgs e) implementation but the idea is there
NOTE2: What you are trying to do is definitely not exception. Configuration based on environment is pretty smart! What must be achieved is standard API usage, e.g. calls via Manager pattern
System.Web.Security.Membership
System.Web.Security.Roles
and not calls to the providers by name.
For my MVC4 application, run in Azure, I store the sessions in a co-located cache. As described in this How-to that Microsoft provide.
I run two small instances, and everything seems to work fine. I can log in to the application, and I remain logged in when I browse around within the application. So the session seem to work on both instances.
However, when I update the session data something like this:
HttpContext.Current.Session["someVar"] = "new value";
That change only seem to have an effect on the instance that handle that particular request. Now as I browse around the application, sometimes I get the initial value and sometimes I get the updated value.
I haven't made any changes to the web.config, so it looks exactly as it do when it gets added by the Nuget package:
<sessionState mode="Custom" customProvider="AppFabricCacheSessionStoreProvider">
<providers>
<add name="AppFabricCacheSessionStoreProvider"
type="Microsoft.Web.DistributedCache.DistributedCacheSessionStateStoreProvider, Microsoft.Web.DistributedCache"
cacheName="default"
useBlobMode="true"
dataCacheClientName="default" />
</providers>
</sessionState>
Do I need to handle sessions in another way when using the Azure cache, or is it something else I'm missing here?
You need to assign an applicationName so that the distributed cache can view the shared state within the same application boundary. See MSDN forum post for reference.
<add name="AppFabricCacheSessionStoreProvider"
type="Microsoft.Web.DistributedCache.DistributedCacheSessionStateStoreProvider, Microsoft.Web.DistributedCache"
applicationName="azureMVC4App"
cacheName="default"
useBlobMode="true"
dataCacheClientName="default" />
If you want to share cache state across application boundaries, you need to assign sharedId
I have a client server application. The client is an asp.net c# site and the server is simply a command line application in c#. I plan on using .NET remoting to access and expose information that is on the server application and preset it to the user viewing the client.
The server application has user objects that i want to use for authentication with the asp.net login controls etc.
I implemented created a custom class "MyMembershipProvider" which implements MembershipProvider but i'm getting very confused now. What do i do next?
i know i need to update the Web.config with a "membership" node but all the examples i've seen have a reference to a connection string, mine does not need a connection string as it will not be using a database etc.
OK so i figured it out.
I don't need a connection string or anything. All i had to do was put:
<membership defaultProvider="Name of the class that you created that implements the MembershipProvider class">
<providers>
<clear/>
<add
name="Name of the class that you created that implements the MembershipProvider clas"
type="fully qualified name of the class that you created that implements the MembershipProvider class" />
</providers>
</membership>
I finally realized that the element above has to be inside the < system.web > element and that fixed it, thanks for your help.
Hope you find this article useful.
http://learn.iis.net/page.aspx/528/how-to-use-the-sample-read-only-xml-membership-and-role-providers-with-iis-70/
You need to better understand why web.config needs a certain configuration, as those database based providers have a reason to use connection strings in web.config. Then you know how to configure your provider (without a connection string as yours does not use database).