I'm trying to figure out how to create a dynamic context, and what I mean by that is I have two databases: one for testing, and one for production. Depending on where my website is hosted, I want my context to be pointing at one of the two. So, in my web.config I have:
<add name="Testing_ChannelsEntities" connectionString="removed for brevity" providerName="System.Data.EntityClient" />
<add name="Production_ChannelsEntities" connectionString="removed for brevity" providerName="System.Data.EntityClient" />
Please don't get hung-up on the fact that I removed the connectionString for this example. Just note that I have a testing and a production connection in the web.config.
So, here is my codebehind that I would expect to create a context to the testing connectionString:
using (ChannelsEntities chEntity = new ChannelsEntities("Testing_ChannelsEntities")) {
// removed the business logic because it's not relevant at all
}
Once execution hits the using statement, I get the following error:
Format of the initialization string does not conform to specification starting at index 0.
What am I missing here? This should be easy to do.
I've done similar. Try this -
using (ChannelsEntities chEntity = new ChannelsEntities("name=Testing_ChannelsEntities")) {}
Try:
using (ChannelsEntities chEntity = new ChannelsEntities(WebConfigurationManager.ConnectionStrings["Testing_ChannelsEntities"].ConnectionString)) {
// removed the business logic because it's not relevant at all
}
We put our connection string in a root web.config. You can reference the connection string by name in your virtual diectory and it will inherit the settings from your root web.config.
Related
I have a javascript bundle that I only want to include when testing, not when the code is deployed to production.
I have added a Property called IsEnabledTestingFeatures. In the BundleConfig.cs file I access it like so:
if(Properties.Settings.Default.IsEnabledTestingFeatures) {
bundles.Add(new ScriptBundle("~/bundles/testing").Include("~/Scripts/set-date.js"));
}
This works correctly.
Now, I only want to include the bundle in my page if this property is set to true.
I have tried the following, but the compiler is complaining that it cannot find the Default namespace:
#{
if( [PROJECT NAMESPACE].Properties.Default.IsEnabledTestingFeatures)
{
#Scripts.Render("~/bundles/testing")
}
}
I tried finding how to access the Scripts.Render functionality from the Controller itself, but have been unsuccessful.
I prefer to add the bundle in the view itself, but will settle for adding it via the Controller.
The ViewBag should not be necessary...
Using appSettings from web.config you don't need to recompile for testing and it deploys easily.
<appSettings>
<add key="TestingEnabled" value="true" />
</appSettings>
View or Layout
#{
bool testing = Convert.ToBoolean(
System.Configuration.ConfigurationManager.AppSettings["TestingEnabled"]);
}
#if (testing) {
#Scripts.Render("~/bundles/testing")
}
And I would define "~/bundles/testing" in BundleConfig regardless of the testing condition unless you wish to bundle this with other scripts.
If you assigned Properties.Default.IsEnabledTestingFeatures from AppSettings then the root of your problem is how you implemented your Properties.
Until, hopefully, an alternative [read: better] solution is proposed, I have implemented it using ViewBag.
BundleConfig.cs
//if testing features are enabled (eg: "Set Date"), include the necessary scripts
if(Properties.Settings.Default.IsEnabledTestingFeatures)
{
bundles.Add(new ScriptBundle("~/bundles/testing").Include(
"~/Scripts/set-date.js"));
}
Controller
public ActionResult Index()
{
ViewBag.IsEnabledTestingFeatures = Properties.Settings.Default.IsEnabledTestingFeatures;
return View();
}
View
#if (ViewBag.IsEnabledTestingFeatures != null && ViewBag.IsEnabledTestingFeatures)
{
#Scripts.Render("~/bundles/site")
}
Some Notes:
I did not implement this via a property in the ViewModel due to this
property/feature being independent of the data being displayed. It
seemed incorrect to associate this condition with individual data
models as it is a site-wide feature.
I used application-level settings because it will be easier to configure this property on a per-environment basis due to the fact we utilize web transforms. Thus each environment can set this property as needed.
I am using XDT-Transform in Visual Studio 2010 to generate multiple config files.
Xml transformation is working fine. But I cannot seem to find way to carry comments from an xml transform file to final file.
Just like there is Insert transform for adding config settings, is there anyway to add comments? Without comments I may have to give up on the whole transform approach.
I've found a possible solution for you.
It is only necessary to denote something as being an Insert at the highest level you are adding it. After that you may just add elements like you would normally.
Meaning this doesn't work to bring over your comment
<appSettings>
<!--My Secret Encryption Key-->
<add key="ENCRYPT_KEY" value="hunter2" xdt:Transform="Insert" />
</appSettings>
But this would
<appSettings xdt:Transform="Remove" />
<appSettings xdt:Transform="Insert" >
<!--My Secret Encryption Key-->
<add key="ENCRYPT_KEY" value="hunter2"/>
</appSettings>
Nothing else requires a transform as it copies over the element entirely.
Upside: You get your comments and don't have to insert xdt:Transform="Insert" into every key element.
Downside: You end up destroying the section entirely and re add it which ends up appending it to the bottom of your Web.config. If the change in total formatting is okay then awesome. Also it requires you recreate the entire section which could increase the size of your transforms.
This isn't exactly what you want, but I find it useful once in a while.
XmlTransform will add comments if they are contained in an added element.
e.g.
<appSettings>
<remove key="comment" value="" xdt:Transform="Insert"><!-- this comment will appear in the transformed config file! --></remove>
</appSettings>
Not possible without writing code.
However, my current solution is to extent the XDT Transform library, by basically following the link: Extending XML (web.config) Config transformation
And here is my example of CommentAppend, CommentPrepend which take comment text as input parameter, as I believe otherwise Insert itself can't work as the comment you would put your xdt:Transform="Insert" will be ignored by XDT Transform as it is comment.
internal class CommentInsert: Transform
{
protected override void Apply()
{
if (this.TargetNode != null && this.TargetNode.OwnerDocument != null)
{
var commentNode = this.TargetNode.OwnerDocument.CreateComment(this.ArgumentString);
this.TargetNode.AppendChild(commentNode);
}
}
}
internal class CommentAppend: Transform
{
protected override void Apply()
{
if (this.TargetNode != null && this.TargetNode.OwnerDocument != null)
{
var commentNode = this.TargetNode.OwnerDocument.CreateComment(this.ArgumentString);
this.TargetNode.ParentNode.InsertAfter(commentNode, this.TargetNode);
}
}
}
And the input web.Release.config:
<security xdt:Transform="CommentPrepend(comment line 123)" >
</security>
<security xdt:Transform="CommentAppend(comment line 123)" >
</security>
And the output:
<!--comment line 123--><security>
<requestFiltering>
<hiddenSegments>
<add segment="NWebsecConfig" />
<add segment="Logs" />
</hiddenSegments>
</requestFiltering>
</security><!--comment line 123-->
I am currently using Reflector to look at Microsoft.Web.XmTransform comes with Visual Studio V12.0 to figure out how it works, but probably it's better to look at the source code itself
As far as I am aware adding comments using XDT-Transform is not possible I'm afraid.
At least it doesn't appear to be mentioned within the XDT-Transform documentation
I built an extension for XDT to handle comment injection and other related tasks.
You can try it online.
I have configured spring security with a ldap server (but continue reading, it's not a problem if you have no knowledge about it, this is really a spring problem). All runs like a charm. Here is the line I use for that:
<ldap-server ldif="" root="" manager-dn="" manager-password="" url="" id="ldapServer" />
If I fill ldif and root attributes, it will run an embeded server:
<ldap-server ldif="classpath://ldap.ldif" root="dc=springframework,dc=org" manager-dn="" manager-password="" url="" id="ldapServer" />
If I fill other fields, it will run a distant server:
<ldap-server ldif="" root="" manager-dn="dc=admin,dc=springframeworg,dc=org" manager-password="password" url="ldap://myldapserver.com/dc=springframeworg,dc=org" id="ldapServer" />
All this stuff run correctly. Now I want to use Spring mechanism to load such parameters from a property file:
So I replace attribute values like this:
<ldap-server ldif="${ldap.ldif.path}" root="${ldap.ldif.root}" manager-dn="${ldap.server.manager.dn}" manager-password="${ldap.server.manager.password}" url="${ldap.server.url}" id="ldapServer" />
and create a property file with:
ldap.server.url=
ldap.server.manager.dn=
ldap.server.manager.password=
ldap.ldif.path=
ldap.ldif.root=
Now, the funny part of the problem. If I fill the following properties in the file:
ldap.server.url=ldap://myldapserver.com/dc=springframeworg,dc=org
ldap.server.manager.dn=dc=admin,dc=springframeworg,dc=org
ldap.server.manager.password=password
ldap.ldif.path=
ldap.ldif.root=
It runs a distant server as expected.
If I fill the property file like this:
ldap.server.url=
ldap.server.manager.dn=
ldap.server.manager.password=
ldap.ldif.path= classpath:ldap.ldif
ldap.ldif.root= dc=springframeworg,dc=org
It does not run, complaining that the ldap url is missing. But the problem is that if I change the spring configuration from:
<ldap-server ldif="${ldap.ldif.path}" root="${ldap.ldif.root}" manager-dn="${ldap.server.manager.dn}" manager-password="${ldap.server.manager.password}" url="${ldap.server.url}" id="ldapServer" />
to (by just removing the reference to the variable ${ldap.server.url})
<ldap-server ldif="${ldap.ldif.path}" root="${ldap.ldif.root}" manager-dn="${ldap.server.manager.dn}" manager-password="${ldap.server.manager.password}" url="" id="ldapServer" />
It runs !
My thoughs are that spring does not replace the attribute value with the property config one if this one is empty. But I find it strange.
Can you give me some clue to understand that ? And what's the best to do to configure my ldap server via a property file ?
EDIT: this is due to a poor design choice (look at accepted answer), an issue has been opened on jira :
https://jira.springsource.org/browse/SEC-1966
Ok, I think this is a spring security bug.
If I debug and look at the class LdapServerBeanDefinition, there is a method called "parse". Here is an extract:
public BeanDefinition parse(Element elt, ParserContext parserContext) {
String url = elt.getAttribute(ATT_URL);
RootBeanDefinition contextSource;
if (!StringUtils.hasText(url)) {
contextSource = createEmbeddedServer(elt, parserContext);
} else {
contextSource = new RootBeanDefinition();
contextSource.setBeanClassName(CONTEXT_SOURCE_CLASS);
contextSource.getConstructorArgumentValues().addIndexedArgumentValue(0, url);
}
contextSource.setSource(parserContext.extractSource(elt));
String managerDn = elt.getAttribute(ATT_PRINCIPAL);
String managerPassword = elt.getAttribute(ATT_PASSWORD);
if (StringUtils.hasText(managerDn)) {
if(!StringUtils.hasText(managerPassword)) {
parserContext.getReaderContext().error("You must specify the " + ATT_PASSWORD +
" if you supply a " + managerDn, elt);
}
contextSource.getPropertyValues().addPropertyValue("userDn", managerDn);
contextSource.getPropertyValues().addPropertyValue("password", managerPassword);
}
...
}
If I debug here, all variables (url, managerDn, managerPassword...) are not replaced by the value specified in the property file. And so, url has the value ${ldap.server.url}, managerDn has the value ${ldap.server.manager.dn} and so on.
The method parse creates a bean, a context source that will be used further. And when this bean will be used, place holders will be replaced.
Here, we got the bug. The parse method check if url is empty or not. The problem is that url is not empty here because it has the value ${ldap.server.url}. So, the parse method creates a context source as a distant server.
When the created source will be used, it will replace the ${ldap.server.url} by empty value (like specified in the property file). And....... Bug !
I don't know really how to solve this for the moment, but I now understand why it bugs ;)
I cannot explain it, but I think you can fix your problem using defaulting syntax, available since Spring 3.0.0.RC1 (see).
In the chageg log you can read: PropertyPlaceholderConfigurer supports "${myKey:myDefaultValue}" defaulting syntax
Anyway, I think that the problem is because "" is valid value, but no value in the property file don't.
I think that url="" works because url attribute is of type xs:token in spring-security XSD and empty string is converted to null (xs:token is removing any leading or trailing spaces, so "" can be recognized as no value). Maybe the value of ${ldap.server.url} is resolved as empty string and that is why you've got an error.
You can try use Spring profiles to define different configurations of ldap server (see Spring Team Blog for details about profiles)
I believe there is an issue here while using place holders. The following will most probably solve the problem:
Create a class which extends PropertyPlaceHolderConfigurer and override its method convertPropertyValue()
in the method you can return the property as empty string if you find anything other than a string which is of type LDAP url i.e. ldap://myldapserver.com/dc=springframeworg,dc=org
Also you need to configure your new specialization of class PropertyPlaceHolderConfigurer in the context file.
Hope this helps.
You can define empty String in the application.properties file as following:
com.core.estimation.stopwords=\ \
Even though I've been a stalker here for ages, this is the first post I'm making. Hopefully, it won't end here and more optimistically future posts might actually be me trying to give a hand to someone else, I do owe this community that much and more.
Now, what I'm trying to do is simple and most probably the reason behind it not working is my own stupidity. However, I'm stumped here.
I'm working on an ASP.Net website that interacts with an SQL Server 2008 R2 database. So far everything has been going okay but updating a row (or more) just won't work. I even tried copying and pasting code from this site and others but it's always the same thing.
In short: No exception or errors are shown when the update command executes (it even gives the correct count of affected rows) but no changes are actually made on the database.
Here's a simplified version of my code (the original had more commands and tons of parameters each, but even when it's like this it doesn't work):
protected void btSubmit_Click(object sender, EventArgs e)
{
using (SqlConnection connection =
new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["ApplicationServices"].ConnectionString))
{
string commandString = "UPDATE [impoundLotAlpha].[dbo].[Vehicle]" +
"SET [VehicleMake] = #VehicleMake" +
" WHERE [ComplaintID] = #ComplaintID";
using (SqlCommand command = new SqlCommand(commandString, connection))
{
SqlTransaction transaction = null;
try
{
command.Connection.Open();
transaction = connection.BeginTransaction(IsolationLevel.Serializable);
command.Transaction = transaction;
SqlParameter complaintID = new SqlParameter("#complaintID", SqlDbType.Int);
complaintID.Value = HttpContext.Current.Request.QueryString["complaintID"];
command.Parameters.Add(complaintID);
SqlParameter VehicleMake = new SqlParameter("#VehicleMake", SqlDbType.VarChar, 20);
VehicleMake.Value = tbVehicleMake.Text;
command.Parameters.Add(VehicleMake);
command.ExecuteNonQuery();
transaction.Commit();
}
catch
{
transaction.Rollback();
throw;
}
finally
{
connection.Close();
}
}
}
}
I've tried this with the "SqlTransaction" stuff and without it and nothing changes.
Also, since I'm doing multiple updates at once, I want to have them act as a single transaction. I've found that it can be either done like this or by use of the classes included in the System.Transactions namespace (CommittableTransaction, TransactionScope...).
I tried all I could find but didn't get any different results.
The connection string in web.config is as follows:
<connectionStrings>
<add name="ApplicationServices"
connectionString="Data Source=localhost;Initial Catalog=ImpoundLotAlpha;Integrated Security=True"
providerName="System.Data.SqlClient"/>
</connectionStrings>
So, tldr; version:
What is the mistake that I did with that record update attempt? (Figured it out, check below if you're having a similar issue.)
What is the best method to gather multiple update commands as a single transaction?
Thanks in advance for any kind of help and/or suggestions!
Edit:
It seems that I was lacking some sleep yesterday cause this time it only took me 5 minutes to figure out my mistake.
Apparently the update was working properly but I failed to notice that the textbox values were being overwritten in Page_Load. For some reason I had this part commented:
if (IsPostBack)
return;
The second part of the question still stands. But should I post this as an answer to my own question or keep it like this?
Have you tried running the query against the database directly (i.e. SQL Management Studio itself)? I'm not sure how you'd implement the "START TRANSACTION... COMMIT TRANSACTION" commands from ASP... for what it's worth we do all our database operations from within stored procedures.
Edited to add solution:
changed to use the constructor that takes a Microsoft.Xrm.Client.CrmConnection rather that a String connection string and it works.
I used the crmsvcutil.exe to generate the data context for our crm environment. When I try to initialize the connection.
This line:
public CSIDataContext(global::System.String name)
: base(name)
throws this error:
Unable to load the connection string name 'Authentication Type=AD; Server=/rest of conn string is here/'
This code resides in a BizLayer class library project and is being called from a win form test project. If both the generated entities class and the calling code are in the same project, I don't get that error.
It sounds like you're passing the full connection string in the constructor rather than the name of the connection string in the connectionStrings node of the app.config/web.config.
The XRM connection string is very similar to an ADO.NET connection string in that it resides in the element in the app.config/web.config. So, you would normally place the full connection string into your config with a name like so:
<connectionStrings>
<add name="XrmConnectionString" connectionString="Authentication Type=AD; Server=http://server.com; User ID=Domain\Username; Password=P#$$w0RD"/>
</connectionStrings>
Then, when you want to initialize the XRM context, you just supply the connection string's name:
var dataContext = new XRMDataContext("XrmConnectionString");
Try that and see if it works for you.