8

I have two MVC web applications, a www.company.com and a solution.company.com

The website www.company.com include links to solution.company.com/Contact but how can I set the href in the View to be able to test them in the development/pre-production/production environments?

Dev:

<a href="http://localhost:88/Contact/">Contact Us</a> 

QA:

<a href="http://qa.solution.company.com/Contact/">Contact Us</a> 

PRD:

<a href="http://solution.company.com/Contact/">Contact Us</a> 
Patrick
  • 2,995
  • 14
  • 64
  • 125

7 Answers7

11

You can use web.config to set different variables. Use separate web.config for each environment. Eg. web.release and web.debug. Same way you can use. Separate files for each environment

If you use, Octopus deployment. Use can set in octopus variables also.

<appSettings>
  <add key="MyVariable1" value="False" />
  <add key="MyName" value="akshay bheda" />
</appSetting>

Now you can easily access this variable and its value from your C# code:

string myVariable = System.Configuration.ConfigurationSettings.AppSettings["MyName"];

Now instead of writing url there, you can use this string instead.

<a href="<%= ConfigurationManager.AppSettings["someKey"] %>">

If you don't want to use Octopus Deployment, You can follow below steps.

1.) Create new Configuration from Configuration Manager. It is located under Build Menu. Configuration Manager and create a new configuration say for eg. Production and select Copy settings from Debug or any other present web.config so you don't have to write again.

2.) After creating a new configuration, Right click on Web.config and click Add Config Transformation Web.config settings after that you will find your new configuration's web.config.

Make the changes in the appSettings section in each of your config and while starting the project, select your build configuration.

It will take the configuration settings from your appSettings section from that respective config.

Akshay Bheda
  • 773
  • 1
  • 6
  • 22
  • Hi, thanks! Can you share a simple example of how can I achieve that? – Patrick Oct 17 '17 at 21:33
  • There is not another way to use the webconfig files, like Dev File and Prod File? – Patrick Oct 17 '17 at 21:59
  • 1
    You can use Octopus deployment. And in the octopus variables, you can set the different values for the same key as per different environments. As per the environment, the value set in the octopus will be used. – Akshay Bheda Oct 17 '17 at 22:35
  • @Svek Version 5.2.3, why? – Patrick Oct 18 '17 at 21:38
  • 2
    @Patrick - you don't need Octopus or anything special added to your project. You can use Web Config Transformations (http://www.c-sharpcorner.com/UploadFile/amit12345/web-config-transformation/) to enable your web.config to have different app settings values depending on your build configuration (debug, release, etc). You can use these to change the URL depending on where you are deploying to. – Tommy Oct 25 '17 at 11:28
  • 2
    @Patrick See this, I have added more content, hope this satisfies your question – Akshay Bheda Oct 26 '17 at 03:55
  • Just a note that the per-configuration transforms are only applied when doing a publish (or manually in VS). So if your build process does a build & package but not a publish, then the transforms are not applied. In which case SlowCheetah is the solution I've used. – Malcolm Oct 28 '17 at 15:07
  • In my opinion `web.config` transformations doesn't look good in this scenario. They are good for debug/release settings, and transform at build time. t I think that parameters like these should be injected in deployment process (not in build process). Injecting variables in octopus deploy is good solution, but it can be a litle bit expensive. Good alternative to octopus is webdeploy/msdeploy. We inject variables by `Parameters.xml` file https://docs.microsoft.com/en-us/aspnet/web-forms/overview/deployment/web-deployment-in-the-enterprise/configuring-parameters-for-web-package-deployment – Sylwekqaz Oct 29 '17 at 21:35
  • 1
    @AkshayBheda Thank you for your help. I have marked your answer has correct because it seems the best one to manage and implement. – Patrick Oct 30 '17 at 11:20
  • @Patrick To award the bounty manually, click on the +50 (or whatever bounty amount was allocated) button on the left side of the answer you want to award: – Akshay Bheda Oct 30 '17 at 11:27
1

If for some reason you do not have an automated deploy system that lets you specify per-environment variables (like Octopus as mentioned in previous answers) there are a couple of other options.

1: Put your settings in a machine.config file for each environment and deploy that config to the appropriate servers.

2: Put your relationships in your config file:

  <appSettings>
    <add key="contact-for-localhost" value="http://localhost:88/Contact/" />
    <add key="contact-for-qa.company.com" value="http://qa.solution.company.com/Contact/" />
    <add key="contact-for-www.company.com" value="http://solution.company.com/Contact/" />
    <add key="contact-for-company.com" value="http://solution.company.com/Contact/" />
  </appSettings>

then ask for the settings by hostname in your controller:

var contactLink = ConfigurationManager.AppSettings[$"contact-for{Request.Url.Host}"]

and pass it to your model.

As you don't have different configurations to switch between, to test this approach you can change your hosts file (c:\System32\drivers\etc\hosts) to fake being each of the environments

127.0.0.1  localhost
127.0.0.1  qa.company.com
127.0.0.1  company.com
127.0.0.1  www.company.com

Then comment out or remove the non-localhost entries to connect to the real servers.

Malcolm
  • 1,239
  • 1
  • 14
  • 25
0

From what you can see in the already existing answers, you're going to need to change your static string hrefs for something defined in compile time. I think you should follow the previous advises and write different tags for the Web.Debug.config and the Web.Release.config, but not to solve your specific situation, mostly to define your connection strings in case you have different database sources for each base.

To solve your specific situation, just use the Url native MVC helper, and replace your static hrefs for something like, <a href="@Url.Content("~/Contact")"> Contact </a>, where "~/" stands for your domain root, regardless of which one it is.

Also, given you didn't write any Controller name before "Contact", I'm assuming you have a ContactController in your application and is reaching its Index View with this address.

Tiramonium
  • 557
  • 5
  • 15
0

What if you made the Model for the MVC View a Dictionary or added a dictionary of settings to the Model returned and simply returned the data from the controller?

<a href="@Model["ContactUsUrl"]">Contact Us</a>

OR

<a href="@Model.Settings["ContactUsUrl"]">Contact Us</a>

Alternatively you could just use a Model that has a ContactUsUrl property

<a href="@Model.ContactUsUrl">Contact Us</a>

Then in your controller code you could use whatever logic you want to decide whether it is DEV, QA or PROD and pull the data for the URL from the associated source, e.g. a database, a config file, a custom settings file. This abstracts the logic and simplifies how your data is used on the page.

This is an alternative to using the web.config directly.

abraganza
  • 135
  • 2
  • 9
0

The solutions proposed are good but a lot of overhead just to switch one url IMHO.

I would take the environment variable approach and set the url accordingly.

Contact.cshtml

@{
    var env = Environment.GetEnvironmentVariable("MY_APP_ENV");
    var url = env == "prod" ? "http://qa.solution.company.com/Contact/" :
              env == "qa"   ? "http://solution.company.com/Contact/" :
                              "http://localhost:88/contact/";
}

<a href="@url">Contact Us</a>

If this is a big project and you can invest some time, I would put this in appSettings and set up parameters.xml for each environment and use it during deployment.

Kevin Aung
  • 803
  • 6
  • 12
0

If you want to use DotNet Core or want to switch to it, then it is best to implement it's environment configuration abilities.

Documentation on official site: Working with multiple environments and Configuration in ASP.NET Core

Here is a good example.

var builder = new ConfigurationBuilder()
    SetBasePath(hostEnv.ContentRootPath)
    .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
    .AddJsonFile($"appsettings.{hostEnv.EnvironmentName}.json", optional: true, reloadOnChange: true);

All you need is to define 3 different appsettings files. And set ASPNETCORE_ENVIRONMENT in your system there you want to do your tests or developing.

Or you can use env.IsEnvironment("environmentname") to check something in runtime.

aleha_84
  • 8,309
  • 2
  • 38
  • 46
-1

You don't need to use app settings for this. Just use the URLHelper that's part of MVC and it'll ensure that the correct hostname is used.

So instead of this:

<a href="http://solution.company.com/Contact/">Contact Us</a> 

You do this:

<a href="@Url.Action("Index", "Contact")">Contact Us</a>

That will generate a link that points to the Contact action within the IndexController.

Another option is to use the HTMLHelper extension method to generate the entire tag for you. In that case, you'd do this:

@Html.ActionLink("Index", "Contact", "Contact Us")
Brendan Green
  • 11,676
  • 5
  • 44
  • 76