I've trying to access an appsettings key value in my vb.net 2.0 web application.
I've put the key in the app.config file:
<appSettings>
<add key="DownloadURL" value="http://<myURL>/" />
</appSettings>
I've followed the instructions here, and it says that I need to access this key like so:
URL = System.Configuration.ConfigurationSettings.AppSettings("DownloadURL")
But I get the following message:
Public Shared Readonly property
AppSettings() As
'System.Collections.Specialized.NameValueCollection'
is obsolete: 'This method is obsolete,
it has been replaced by
System.configuration!System.configuration.configurationmanager.AppSettings'
I tried to replace the old method with the new one, but it does not exist.
Strange, since I've done a similar thing with a web app and it did exist there.
Add a reference to System.Configuration.dll.
Here's an explanation.
Related
I am building the sample MvcMovie tutorial for ASP.NET MVC 4. I'm using EntityFramework Code First features and created a connectionString as follows.
<add name="MoveDBContext"
connectionString="Data Source=(LocalDB)\v11.0;AttachDbFilename=|DataDictionary|\Movies2.mdf;Integrated Security=True"
providerName="System.Data.SqlClient"
/>
Everything worked fine at this point. But then I realized that I named my connection string MoveDBContext instead of MovieDBContext and, being the perfectionist I renamed it. After doing this I now receive an error in my MoviesController/Index method.
public class MoviesController : Controller
{
private MovieDBContext db = new MovieDBContext();
public ActionResult Index()
{
return View(db.Movies.ToList()); // Error: Invalid value for key 'attachdbfilename'
}
...
}
If I change the name back to MoveDBContext the error goes away.
Can anyone tell me where this original name is being referenced?
EF, by default, looks for a connection string with the same name as the type that extends DbContext.
Or, better put by Scott:
By default, when you create a DbContext class with EF code-first, it
will look for a connection-string that matches the name of the
context-class. Since we named our context class “NerdDinners”, it
will by default look for and use the above “NerdDinners” database
connection-string when it is instantiated within our ASP.NET
application.
Edit:
After looking closer, I think your connection string is the problem. You've got DataDictionary instead of DataDirectory. Try this (line feeds added for readability):
<add name="MovieDBContext"
connectionString="Data Source=(LocalDB)\v11.0;
AttachDbFilename=|DataDirectory|\Movies.mdf;
Integrated Security=True"
providerName="System.Data.SqlClient" />
Apparently, as Ken said, the MoveDBContext was not being referenced.
I removed the entire connectionString from the web.config and everything still functioned correctly.
So, it still begs the question, "How did Visual Studio know to create a database in my SQLExpress instance?" and "Where is that configured at?"
I am struggling with getting a simplemembership scenario working in my EntityFramework / MVC4 / DatabaseFirst project. I've found plenty of examples for working with code first, but nothing for DB first.
The problem I'm encountering is the the InitializeDatabaseConnection is throwing an error ("Unable to find the requested .Net Framework Data Provider. It may not be installed.") The code looks like this :
WebSecurity.InitializeDatabaseConnection("DALEntities", "tblContacts1", "ContactID", "EMail", autoCreateTables: true);
I am not sure what DataProvider is failing. If I try to trace 'into' the InitializeDatabaseConnection call, it immediately throws the error.
What am I missing?
Info:
DALEntities is the name of the connectionString that the rest of EF uses. The following code works just fine....
public ActionResult Test() {
using (var db = new DALEntities()) {
var query = from i in db.TBLINVENTORies
orderby i.ITEMNAME
select i;
var cnt = query.Count();
string str = "Total Inventory: " + cnt;
return Content(str);
}
}
My connection strings section from the web.config:
<connectionStrings>
<add name="DALEntities" connectionString="metadata=res://*/DAL.DAL.csdl|res://*/DAL.DAL.ssdl|res://*/DAL.DAL.msl;provider=System.Data.SqlClient;provider connection string="data source=SOMECOMPUTER;initial catalog=SOMEDB;persist security info=True;user id=SOMEID;password=SOMEPASS;multipleactiveresultsets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
</connectionStrings>
This post seems to be asking the same question (but in context of model-first), but there is no solution yet : Using SimpleMembership with EF model-first
Also, I see that there is an overload for WebSecurity.InitializeDatabaseConnection() with the help text: Initializes the membership system ((blah blah <snip> ProviderName: the name of the ADO.NET data provider. If you want to use Microsoft SQL Server, the WebMatrix.WebData.WebSecurity.InitializeDatabaseConnection(String, String, String, String, Boolean) overload is recommended . I do wish to connect to a MSSQL server...will this be required?
The provider giving you trouble is the one specified in your connection string which is System.Data.EntityClient. I suspect the problem is because your project is database-first whereas the simple membership is using code-first. I do not think you can mix these approaches in a single database. Try putting it back to where the DefaultConnection is used for IntializeDatabaseConnection. There should have been a DefaultConnection in your web.config generated by the MVC4 scaffolding. This connection string usually uses System.Data.SqlClient as the provider.
If you want to keep the simple membership in the database used to store domain information (i.e. DALEntities) then you will need to change your method for using EF on the domain to code-first. If you want to keep your project database-first you need to design your own membership schema in the database and develop custom member and role providers. This is probably the best approach if you are really trying to integrate user information into your domain model.
For simplicity and clarity keep two connection strings pointing to the same database. One for EF (doesn't matter if code first or data first) and one for your WebSecurity stuff. (As Chad and Erik said)
<add name="DataEntities" connectionString="metadata=res://*/Models.DataEntities.csdl|res://*/Models.DataEntities.ssdl|res://*/Models.DataEntities.msl;provider=System.Data.SqlClient;provider connection string='data source=[YOUR_SERVER];initial catalog=[YOUR_DATABASE];integrated security=True;MultipleActiveResultSets=True;App=[YOUR_APP_NAME]'" providerName="System.Data.EntityClient" />
<add name="DataDB" connectionString="data source=[YOUR_SERVER];initial catalog=[YOUR_DATABASE];integrated security=True;MultipleActiveResultSets=True;App=[YOUR_APP_NAME]" providerName="System.Data.SqlClient" />
Note that the providers are different: EF uses System.data.EntityClient and non-EF one uses System.Data.SqlClient.
I've been getting this error when I try and use my model container:
No connection string named 'PFModelContainer' could be found in the
application config file.
I have my edmx file in a separate project. I checked the app.config file and my model was there, and I also put it in my main project app.config file. Still doesn't work. Here's the connection string:
<connectionStrings>
<add name="PFModelContainer"
connectionString="metadata=res://*/PFModel.csdl|res:
//*/PFModel.ssdl|res://*/PFModel.msl;
provider=System.Data.SqlServerCe.3.5;
provider connection string="
Data Source=C:\Documents and Settings\Jon\My Documents\Visual
Studio 2010\Projects\SpreadsheetAddIn
\SpreadsheetAddIn\bin\Debug\PFData.sdf;
Password=password""
providerName="System.Data.EntityClient" />
</connectionStrings>
Here's how the context is called:
Private mdbContext As New PFModelContainer
Which goes to:
Partial Public Class PFModelContainer
Inherits DbContext
Public Sub New()
MyBase.New("name=PFModelContainer")
End Sub
I thought the answer would be similar to what happened to this guy. But unfortunately his solution doesn't work with mine.
Update:
I've noticed the error isn't caught until I hit this code. It occurs when I do the linq query on the third line.
Dim dbContext As New PFModelContainer
Dim dbAccount As IQueryable(Of Account)
dbAccount = From a In dbContext.Accounts
Where (a.AccountName = "Hello")
Select a
Update (What I've tried for connection strings - that I can remember):
1 Main Project: --> Default Creation
<add name="PFModelContainer"
connectionString="metadata=res://*/PFModel.csdl|
res://*/PFModel.ssdl|
res://*/PFModel.msl;
provider=System.Data.SqlServerCe.3.5;
provider connection string="
Data Source=C:\Documents and Settings\Jon\My Documents\Visual Studio 2010\Projects\SpreadsheetAddIn\PFDatabase\bin\Debug\PFData.sdf;
Password=password""
providerName="System.Data.EntityClient" />
Library:
<add name="PFModelContainer"
connectionString="metadata=res://*/PFModel.csdl|
res://*/PFModel.ssdl|
res://*/PFModel.msl;
provider=System.Data.SqlServerCe.3.5;
provider connection string="
Data Source=|DataDirectory|\bin\Debug\PFData.sdf;
Password=password""
providerName="System.Data.EntityClient" />
2 Main Project: --> Replace * with PFDatabase
<add name="PFModelContainer"
connectionString="metadata=res://PFDatabase/PFModel.csdl|
res://PFDatabase/PFModel.ssdl|
res://PFDatabase/PFModel.msl;
[...Same...]
Library:
[...Same w/ modifications...]
3 Main Project: --> Replace res://*/ with .\
<add name="PFModelContainer"
connectionString="metadata=.\PFModel.csdl|
.\PFModel.ssdl|
.\PFModel.msl;
[...Same...]
Library:
[...Same w/ modifications...]
4 Main Project: --> Replace res://*/ with ~\
<add name="PFModelContainer"
connectionString="metadata=~\PFModel.csdl|
~\PFModel.ssdl|
~\PFModel.msl;
[...Same...]
Library:
[...Same w/ modifications...]
If you are placing your edmx model in a separate class library, add an app.config to that class library and add the connection string to that config.
Additionally, if your datamodel resides inside a namespace then you will have to include the full namespace in your resource path:
For example, if you placed your edmx file in an assembly called MyProject.DataLayer and the namespace for the generated code is MyProject.DataLayer.DataModel, then your configuration string should be:
<add name="PFModelContainer"
connectionString="metadata=res://*/DataModel.PFModel.csdl|res:
//*/DataModel.PFModel.ssdl|res://*/DataModel.PFModel.msl;
provider=System.Data.SqlServerCe.3.5;
provider connection string="
Data Source=C:\Documents and Settings\Jon\My Documents\Visual
Studio 2010\Projects\SpreadsheetAddIn
\SpreadsheetAddIn\bin\Debug\PFData.sdf;
Password=password""
providerName="System.Data.EntityClient" />
Got some help from experts exchange on this one. Ended up doing a work around (not sure why it wasn't working like it should), since I'm using DbContext instead of EntityObject I had to create my own overrideable procedure like (the second one below):
Public Sub New()
MyBase.New("name=PFModelContainer")
End Sub
Public Sub New(ByVal connectionString As String)
MyBase.New(connectionString)
End Sub
I then had to create my own connection string, which is basically what the original code generated, so, I'm not sure why it wasn't working from the app.config file. Maybe there's a bug in the program that will be fixed the next go around? Hopefully that was it, either that or I did something wrong, mystery.
How do I use current date & time as the value for the findValue attribute in the ServiceCertificate config when using "FindByTimeValid" for the x509FindType? Using DateTime.Now as below obiously doesn't work but neither does "2010-10-20 14:35:28Z". I have two certificates on the server with the same details as one of them has expired which is why I'm using this find type value.
For example:
<serviceCredentials>
<serviceCertificate findValue="DateTime.Now" x509FindType="FindByTimeValid" storeLocation="LocalMachine" storeName="My"/>
</serviceCredentials>
Edit: I fixed this by removing the expired certificate but I'm still curious if this is possible.
Thanks
Keith
As no-one seems slightly interested in this question (2 views in a month and I think at least one of them was me) I decided to break out Reflector and have a look at the process and have found the following.
In the X509Certificate2Collection.FindCertInStore(SafeCertStoreHandle safeSourceStoreHandle, X509FindType findType, object findValue, bool validOnly) method of the System.ServiceModel assembly we have the following code
case X509FindType.FindByTimeValid:
if (findValue.GetType() != typeof(DateTime))
{
throw new CryptographicException(SR.GetString("Cryptography_X509_InvalidFindValue"));
}
As you can see from the signature the findValue comes in as an object which I think is in turn loaded by the config parser as a string which means this will never work.
So the answer is you can't do this though the xml config but you can if you do it programmatically.
So I currently have 2 WSDLs added as Service References in my solution. They look like this in my app.config file (I removed the "bindings" field, because it's uninteresting):
<system.serviceModel>
<client>
<endpoint address="http://localhost:8080/query-service/jse" binding="basicHttpBinding" bindingConfiguration="QueryBinding" contract="QueryService.Query" name="QueryPort" />
<endpoint address="http://localhost:8080/dataimport-service/jse" binding="basicHttpBinding" bindingConfiguration="DataImportBinding" contract="DataService.DataImport" name="DataImportPort" />
</client>
</system.serviceModel>
When I utilize a WSDL, it looks something like this:
using (DataService.DataClient dClient = new DataService.DataClient())
{
DataService.importTask impt = new DataService.importTask();
impt.String_1 = "someData";
DataService.importResponse imptr = dClient.importTask(impt);
}
In the "using" statement, when instantiating the DataClient object, I have 5 constructors available to me. In this scenario, I use the default constructor:
new DataService.DataClient()
which uses the built-in Endpoint Address string, which I assume is pulled from app.config. But I want the user of the application to have the option to change this value.
1) What's the best/easiest way of programatically obtaining this string?
2) Then, once I've allowed the user to edit and test the value, where should I store it?
I'd prefer having it be stored in a place (like app.config or equivalent) so that there is no need for checking whether the value exists or not and whether I should be using an alternate constructor. (Looking to keep my code tight, ya know?)
Any ideas? Suggestions?
EDIT
Maybe I should ask about these Alternate constructors as well.
For example, one of them looks like this:
new DataService.DataClient(string endPointConfigurationName,
string remoteAddress)
What values could get passed for "endPointConfigurationName" and "remoteAddress"?
EDIT2
Answering my own questions here, the "endPointConfigurationName" appears to be the same as the "name" in the app.config XML and the "remoteAddress" is formatted the same as "endpoint address" in the app.config XML.
Also! The answer to my first question about getting the EndPointAddresses is the following:
ClientSection clSection =
ConfigurationManager.GetSection("system.serviceModel/client") as ClientSection;
ChannelEndpointElementCollection endpointCollection =
clSection.ElementInformation.Properties[string.Empty].Value as ChannelEndpointElementCollection;
Dictionary<string, string> nameAddressDictionary =
new Dictionary<string, string>();
foreach (ChannelEndpointElement endpointElement in endpointCollection)
{
nameAddressDictionary.Add(endpointElement.Name,
endpointElement.Address.ToString());
}
EDIT3
Ok, I think I've figured out the 2nd half (and thus, full solution) to my problem. I found this on another website and I modified it to meet my needs:
Configuration configuration;
ServiceModelSectionGroup serviceModelSectionGroup;
ClientSection clientSection;
configuration =
ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
serviceModelSectionGroup =
ServiceModelSectionGroup.GetSectionGroup(configuration);
clientSection = serviceModelSectionGroup.Client;
foreach (ChannelEndpointElement endPt in clientSection.Endpoints)
{
MessageBox.Show(endPt.Name + " = " + endPt.Address);
}
configuration.Save();
With this code, we have access to the clientSection.Endpoints and can access and change all the member properties, like "Address". And then when we're done changing them, we can do configuration.Save() and all the values get written out to a user file.
Now here's the catch. In debug mode, the "configuration.save()" does not appear to actually persist your values from execution to execution, but when running the application normal (outside of debug mode), the values persist. (Which is good.) So that's the only caveat.
EDIT4
There is another caveat. The changes made to the WSDLs do not take effect during runtime. The application needs to be restarted to re-read the user config file values into memory (apparently.)
The only other thing that I might be interested in is finding a way (once the values have been changed) to revert the values to their defaults. Sure, you can probably delete the user file, but that deletes all of the custom settings.
Any ideas?
EDIT5
I'm thinking Dependency Injection might be perfect here, but need to research it more...
EDIT 6
I don't have comment privileges but you need to run
ConfigurationManager.RefreshSection("client");
to have the cache updated so that changes happen immediately.
If you're using Microsoft Add Web Reference to create your service reference, then I think you may have trouble changing the connection programmatically. Even if you did change the auto generated code, as soon as you did an Update Service Reference it'd be overwritten.
You're best bet is to scratch Microsoft's auto generated code and build your own WCF classes. It's not difficult, and offers lots of flexibility / scalability.
Here's an excellent article on this very subject.
As for storing the custom addresses, it would depend on your app whether it's a Silverlight, Windows or web app. My personal choice is the database.