Using web services in different environments - asp.net

We have a series of web services that live in different environments (dev/qa/staging/production) that are accessed from a web application, a web site, and other services. There are a few different service areas as well. So for production, we have services on four different boxes.
We conquered the db connection string issue by checking the hostname in global.asax and setting some application wide settings based on that hostname. There is a config.xml that is in source control that list the various hostnames and what settings they should get.
However, we haven't found an elegant solution for web services. What we have done so far is add references to all the environments to the projects and add several using statements to the files that use the services. When we checkout the project, we uncomment the appropriate using statement for the environment we're in.
It looks something like this:
// Development
// using com.tracking-services.dev
// using com.upload-services.dev
// QA
// using com.tracking-services.qa
// using com.upload-services.qa
// Production
// using com.tracking-services.www
// using com.upload-services.www
Obviously as we use web services more and more this technique will get more and more burdensome.
I have considered putting the namespaces into web.config.dev, web.config.qa, etc and swapping them out on application start in global.asax. I don't think that will work because by the time global.asax is run the compilation is already done and the web.config changes won't have much effect.
Since the "best practices" include using web services for data access, I'm hoping this is not a unique problem and someone has already come up with a solution.
Or are we going about this whole thing wrong?
Edit:
These are asmx web services. There is no url referenced in the web.config that I can find.

Make one reference and use configuration to switch the target urls as appropriate. No reason to have separate proxies at all.

Related

Setting project url in VS2015 ASP.NET 5 Web API application

I'm trying to create a Web API project and a client-side web project, where the web project can access the API via ajax. Currently my project looks like this:
I saw this answer on here: Setting app a separate Web API project and ASP.NET app, which explains how the project url can be set to localhost:[port]/api.
But for ASP.NET 5 projects, the properties only have 3 tabs (as opposed to the several found in ASP.NET 4 projects):
What I'm wondering is:
Do I have to set this option somewhere else? (i.e project.json)
How would this work when I publish? Ideally I'd want [websiteURL]/api to serve up my API, whereas that link explicitly put localhost:8080.
Is having these as two projects a good idea? I could easily put API and web in the same project, but I like the separation of client-side and server-side logic.
Any help would be appreciated!
First Point:
Generally speaking in ASP.NET 5, the routing defaults are very good and should work out of the box without much in the way of configuration. You can use configuration and/or attribute based routing in your application (with a detailed overview of both here), although my personal preference is for the attributed approach. Provided you have the following line in your Startup.cs file (which you should have in a new project):
app.UseMvc();
you should be able to route requests to your api controllers in the fashion required (i.e. "/api/...") simply by using [Route] attributes as below (example taken from a standard generated ASP.NET 5 Web API application)
[Route("api/[controller]")]
public class ValuesController : Controller
{
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
}
The above example will route any GET request made to "/api/values".
While this approach can be used to handle requests made to your api, in order to deliver the files needed for your front end javascript application/single page app, you will need to enable static file serving. If you add the following to the Configure method in your Startup.cs class:
app.UseStaticFiles();
this will allow your application to serve those static files - by default, these are served from the ‘wwwroot’ folder, although this can be changed in the project.json file if required. The files needed for your front end app should then be added to this folder. A tutorial on serving static files can be found here.
Second Point:
In my experience this will not be an issue when you publish your website - provided your server is set up correctly, you will not need to include the port when making a request - navigating to [yourwebsitename]/api/... will suffice.
Third point:
In my opinion this entirely depends on how large the project is likely to grow, although preference and opinion will vary from developer to developer. Generally speaking, if the project will remain small in scope then keeping both in a single project is perfectly ok, as unnecessary complexity is reduced. However it is also very useful as you have pointed out, to maintain a separation of concerns between projects. So aside from the organisational advantage of your approach, the respective dependencies of the two projects are/will be kept separate also.

Deploying AD FS web application to multiple environments

Background:
I have an ASP.NET web app configured for federation with AD FS. I'm using VS 2012, and have TFS for source control, builds and deployments.
We're currently deploying by copying the built files from the build server (TFS) to the alpha environment. From there we would copy from alpha to beta, then from beta to production. So there is not a unique build for each environment. The way we're handling environment-specific settings right now is there is one config file that has all the settings for each environment Let's call this EnvironmentSpecificSettings.config (I'll refer to it below). There is a static file on each server that indicates which environment the server should be in, and so when that config file is read in, the matching settings can be applied.
The problem:
The ADFS configuration is handled in the web.config. There are a few things that are specific to the environment. How might I handle this within my current deployment paradigm? I had a couple of ideas:
include a file reference in the web.config that reads in a static environment-specific file that would not be part of the deployment.
Try to pull something off in Application_Start that would read in settings from EnvironmentSpecificSettings.config (mentioned above) and alter the web.config.
Try to tweak the configuration of the WSFederationAuthenticationModule at runtime
the first idea (#1) is less than optimal because it requires files hanging around outside of source control and outside of deployments, however it should work easily enough. Next, #2 I kinda think isn't possible. I'm not sure you can change your web.config like I am hoping, but maybe? Finally, #3 Is only reasonable because I'm in a special situation where I'm not doing regular passive authentication, instead I'm manually redirecting to adfs, so I have a chance to change settings, such as injecting the whr parameter to avoid HRD. So, it might be possible, however, I'm not sure how or if you can change some of these values on the fly such as thumbprint, or wsFederation issuer or realm.
Does anyone have any better ideas or experience in handling environment-specific settings without doing the visual studio web deploys with transforms?

how to deploy flex app using different web service urls?

Is there some sort of configuration settings in FlashBuilder 4.5 where you can easily switch between webservice urls? Right now I have to delete and recreate the web service every time I switch from local to production and vice versa.
The need/requirement is this – Since I work in a startup, we keep changing servers, and their IP addresses. And being a service oriented application – I need to be able to edit the webservice endpoints in my Flex application in a easy manner every time this happens.
My Solution for this -
Assumption is that my webservice endpoint looks like this -
http:////ListAllServices/
1) Create a file config.xml in a folder named “settings” that sits in the root folder of your Flex application – outside the “src” folder. And the config.xml will be a simple xml file of the following format -
localhostTestFlexApp
At the end of this exercise the directory structure of your flex source code will look like this -
flex_src(root of the source code)
-com(some source folder)
–testapp
—view
—
-images
-settings
–config.xml
-appName.mxml
2) Now in your application code, setup a HTTPService object either in mxml or action script. Set the url of that object to this value- “settings/config.xml” – And the above xml fiel containing the current settings will be loaded into memory .
Now you can store these values in a singleton object and construct your Webservice call at runtime.
And whenever you want to move this to a new server in production, edit the tag of your config.xml and you should be good to go.
And this can be automated as well via the EnvGen ant task.
This is not the best way but yes it is very helpful while switching among servers.
Alrighty... The way I was doing it before in fact worked. The problem was browser caching.
For the benefit of others I modified the subsclass for the generated service and replace the wsdl variable with whatever endpoint I need.

How to configure WCF in a separate dll project

I'm developing a web application (ASP.NET 3.5) that will consume a number of web services. I have created a separate dll-project for each web service: these projects contains the service reference and client code.
However, the calling website MUST have the <system.serviceModel> information (the <bindings> and <client> nodes) in it's web.config, even though this information is also in the dll's app.config file! I have tried copying the serviceclass.dll.config over to the bin directory of the website, but this didn't help.
Is there any way to centralize the configuration of a WCF client?
I've only limited WCF experience, all with BasicHTTP bindings. But I'm allergic to WCF's xml files and have managed to avoid them thus far. I don't recomend this generally but I put the configuration details in my apps existing configuration store and then apply them programatically. E.g. With a Web service proxy I use the constructor for the Client that takes 'bindings'and 'endpoint' and programatically apply the settings to the bindings & endpoint.
A more elegent solution appears to be descibed here: Reading WCF Configuration from a Custom Location, but I haven't tried it yet.
From my experience, library projects never read app.config.
So you can really delete the file because it is not used. The library's host configuration is read instead, so that is the only place the endpoint and binding configuration should be.
It's possible to forgo xml config and build up the Binding and Endpoint classes associated with the service in the constructor or a custom "Service Factory". iDesign has some good information on this:
http://www.idesign.net/idesign/DesktopDefault.aspx?tabindex=5&tabid=11
(See In Proc Factory)
In their approach, you set attributes on your services to specify at a high level how they should work (ie [Internet], [Intranet], [BusinessToBusiness]), and the service factory configures the service according to best practices for each scenario. Their book describes building this sort of service:
http://www.amazon.com/Programming-WCF-Services-Juval-Lowy/dp/0596526997
If you just want to share configuration XML config, maybe use the configSource attribute to specify a path for configuration: http://weblogs.asp.net/cibrax/archive/2007/07/24/configsource-attribute-on-system-servicemodel-section.aspx
Remember that a configuration file is is read by an executable that has an entry point. A library dll does not have an entry point so it is not the assembly that will read it. The executing assembly must have a configuration file to read.
If you would like to centralize your web configs then I would suggest you look into nesting them in IIS with virtual directories. This will allow you to use the configuration inheritance to centralize whatever you need.
There are 2 options.
Option 1. Working with channels.
If you are working with channels directly, .NET 4.0 and .NET 4.5 has the ConfigurationChannelFactory. The example on MSDN looks like this:
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = "Test.config";
Configuration newConfiguration = ConfigurationManager.OpenMappedExeConfiguration(
fileMap,
ConfigurationUserLevel.None);
ConfigurationChannelFactory<ICalculatorChannel> factory1 =
new ConfigurationChannelFactory<ICalculatorChannel>(
"endpoint1",
newConfiguration,
new EndpointAddress("http://localhost:8000/servicemodelsamples/service"));
ICalculatorChannel client1 = factory1.CreateChannel();
As pointed out by Langdon, you can use the endpoint address from the configuration file by simply passing in null, like this:
var factory1 = new ConfigurationChannelFactory<ICalculatorChannel>(
"endpoint1",
newConfiguration,
null);
ICalculatorChannel client1 = factory1.CreateChannel();
This is discussed in the MSDN documentation.
Option 2. Working with proxies.
If you're working with code-generated proxies, you can read the config file and load a ServiceModelSectionGroup. There is a bit more work involved than simply using the ConfigurationChannelFactory but at least you can continue using the generated proxy (that under the hood uses a ChannelFactory and manages the IChannelFactory for you.
Pablo Cibraro shows a nice example of this here: Getting WCF Bindings and Behaviors from any config source
First of all class libraries (DLLs) do not have their own configuration, however they can read the configuration of their host (Web/Executable etc.). That being said, I still maintain an app.config file on the library projects as a template and easy reference.
As far as the service configuration itself is concerned, WCF configuration can make somebody easily pull their hair out. It is an over-engineered over-complicated piece. The goal of your applications should be to depend least on the configuration, while maintaining flexibility of deployment scenarios your product is going to come across.

Specifying connection string in config file for a class library and re-use/modify in ASP.NET Web Application

How can one specify the connection string in a config file of a class library and later modify this when used in a ASP.NET Web Application?
The Class library is a data access layer that has a Dataset connecting to a database based on a connection string specified in a config file (Settings.settings/app.config).
This class library is used in a web application where user inputs data and is written to the database using the DAL classes & methods exposed in the class library.
Now, I want to migrate this application from development environment to testing environment and later to production. The problem I'm facing is that after migrating to testing, the app in testing still connects to development database. I've changed the connection string mentioned in <class library>.dll.config file but this seems to have no impact.
Can someone explain the right way to achieve this? Thanks in advance for any help. Cheers.
With the .config files the name has to match the main executing assembly. For example I had a situation like yours, I needed a class library to have its settings in a .dll.config file. While it was able to reference it the actual application would not be able to read the config file because it was expecting .exe.config. Renaming the .dll.config to .exe.config fixed the problem.
In your case migrating your connection strings from .dll.config to web.config should fix your problem!
Good luck!
Joshua is partly right ... For posterity I would like to add a bit more to this answer as I have delt with the same problems on several occasions. First, one must consider their architecture. There are several issues you can run into with .config files in ASP.NET based on deployments.
Considering the architectural ramifications:
Single tier (one server):
A simple web application may be able to leverage a reference to the sites Web.config file and resolve your issues. This would be a fine solution for a single tier application. In the case of a windows application leveraged as a .exe file, the App.config will work too.
Multi-tier (more than one server):
Here is where things became a bit hairy for me the first time I was working with .config files across boundries. Remember the hierarchy of the config structure and keep this in mind (MSDN Article on .Config structure) - there is a machine.config at the root in the appropriate ASP.NET folder. These reside at each physical server. These are overridden by the site Web.config (or App.config) which are in turn overridden by subfolder .config files. If you have more than one .config file you may want to use one of the methods to pass the file path for the specific .config you want to use. More importantly, these files each may have connection information. ASP.NET's machine.config holds some for the framework ... so you should at least be senstive to the fact this is an "inheritance" chain. Second, any changes to the Web.config file once deployed will tell the application to restart. This will result in loss of state (bad if you have active users on the site). The way around this is to keep a separate .config file (e.g. connections.config) and put a reference to that file in the Web.config. This will allow you to change the connection information (e.g. password) without having to restart the application. Here is a link to more info: MSDN: Working with Configuration Files. This article lays out all the details you need to be aware of in a normal server / IIS deployed application. Keep in mind that the .config files are mainly intended for applications, not libraries. If you have several tiers, chances are you are using some communicaiton / messaging layer (e.g. WCF). This will have / allow its own Web.config. You can keep connection strings there (and encrypt them if needed), but better yet, put them in a second file referenced by the Web.config for manageability. One final point, if you are ever going to consider the cloud, .config files are wrapped for application deployments which in effect removes all of the benefits they offer in terms of "not having restart or redeploy". Azure deployments will want to consider this article to save themselves from nightmares of maintenance: Bill Lodin blog - Configuration files in Azul / Cloud. One other point on this article – great example on how to programmatically select configuration depending on deployment! Be sure to check that out if you want to add flexibility to deploy in or out of the cloud .
I hope these points saves all of you time and headaches. I know I lost a couple days of programming time dealing with these issues ... and it was hard to find all the reasons in one place why may app was not "implementing" its connection object. Hopefully this will save you all from the same fate I had.

Resources