0
votes

I've got a web app running with a web job running on Azure. I've linked my solution to Bitbucket in order to use continuous deployment and that part is working fine.

The problem I'm having is that whenever I deployment (and rebuild) occurs, neither my web app or web job can access my Azure storage table as the value returned from CloudConfigurationManager.GetSetting("StorageConnectionString") returns a blank value.

I've just checked via FTP and both my web app and webjob has the relevant entry in their respective config file i.e. StorageConnectionString

<appSettings>
    ...
    <add key="StorageConnectionString" 
         value="DefaultEndpointsProtocol=https;
         AccountName=MyASPMVCSite;AccountKey=ABCD==" />
</appSettings>

I call the following code to read the StorageConnectionString value from my appSettings

var cloudStorageAccount = 
CloudStorageAccount.Parse(
CloudConfigurationManager.GetSetting("StorageConnectionString"));

but when I try to output this value to either my home page or my webjob log, it "displays" as an empty value.

When I publish my project via a Web Deploy directly from VS 2013 to Azure, everything works as expected. My StorageConnectionString value is displayed on both my home page and web job log.

Any ideas why?

Thanks.

UPDATE

If you have time to spare and want to try to reproduce it, here is the code.

As the project is so small, but I don't believe the problem lies with the code. I think it lies with the deployment.

I created a basic ASP.NET MVC web application and then added a webjob project as a second project to the solution. It is a very basic test sample that I'm following from MS Virtual Academy. All it does is insert a random number into a storage table whenever the web job is called.

I've added the following code the ASP.NET MVC web app:

  1. Changed the index.cshtml and added the following at the bottom the file:

    <h1>Table Endpoint:</h1>
    @Html.Raw(ViewBag.TableEndpoint)
    <br />
    <h1>Azure Results:</h1>
    @Html.Raw(ViewBag.Result)
    
  2. Changed the HomeController.cs to:

    public ActionResult Index()
    {
        Time = string.Format("{0:MM/dd/yyyy hh:mm:ss tt}", DateTime.UtcNow);
    
        long ticks = DateTime.MaxValue.Ticks;
        DateTime utcNow = DateTime.UtcNow;
        string orderingTime = string.Format("{0:D19}", ticks - utcNow.Ticks);
    
        ViewBag.Message = "Modify this template to jump-start 
        your ASP.NET MVC application.";
    
        var cloudStorageAccount = CloudStorageAccount.
        Parse(CloudConfigurationManager.
        GetSetting("StorageConnectionString"));
    
        Console.WriteLine(cloudStorageAccount.
        TableEndpoint.ToString());
    
        var tableReference = cloudStorageAccount.
        CreateCloudTableClient().
        GetTableReference("Activity");
    
        var activities = (
            from g in tableReference.CreateQuery<Activity>()
            where (g.PartitionKey == "Demo")
            && string.Compare(g.RowKey, 
            orderingTime, 
            StringComparison.Ordinal) > 0
            select g);
    
        string result = string.Empty;
        if (activities != null)
        {
            foreach (var activity in activities)
            {
                result += string.Format("<p>{0} => {1}</p>", 
                activity.Date.ToLongDateString(), 
                activity.Number.ToString());
            }
        }
    
        ViewBag.TableEndpoint = cloudStorageAccount.TableEndpoint.ToString();
        ViewBag.Result = result;
    
        return View();
    }
    
  3. I've added a class to the Models folder i.e. Activity.cs

    public class Activity : TableEntity
    {
       public DateTime Date { get; set; }
       public int Number { get; set; }
    }
    

In the web job project, the following was changed:

  1. The Program.cs was changed to:

    static void Main()
    {
        //var host = new JobHost();
        //// The following code will invoke 
        //a function called ManualTrigger and 
        //// pass in data (value in this case) to the function
        //host.Call(typeof(Functions).
        //GetMethod("ManualTrigger"), new { value = 20 });
    
        var cloudStorageAccount = 
            CloudStorageAccount.Parse(
            CloudConfigurationManager.
            GetSetting("StorageConnectionString"));
    
        Console.WriteLine(
        cloudStorageAccount.TableEndpoint.ToString());
    
        var tableReference = cloudStorageAccount.
            CreateCloudTableClient().
            GetTableReference("Activity");
    
        tableReference.CreateIfNotExists();
    
        Random random = new Random();
    
        var activity = new Activity()
        {
            Number = random.Next(100)
        };
    
        var tableOperation = TableOperation.Insert(activity);
    
        try
        {
            tableReference.Execute(tableOperation);
        }
        catch (Exception)
        {
            throw;
        }
    
      //#if DEBUG
        Console.WriteLine("{0} number generated.", 
        activity.Number.ToString());
        Console.ReadLine();
     //#endif
    }
    
  2. I've also added a new class i.e. Activity.cs

    public class Activity : TableEntity { public DateTime Date { get; set; } public int Number { get; set; }

    public Activity()
    {
        var ticks = DateTime.MaxValue.Ticks;
        var utcNow = DateTime.UtcNow;
    
        this.PartitionKey = "Demo";
        this.RowKey = string.Format("{0:D19}", ticks - utcNow.Ticks);
        this.Date = DateTime.Now;
    }
    

    }

That's it. Every time you run the web job it will generate a random number and insert it into an Activity table. When running the web app, it will simply list all the numbers that were added to the table at the bottom of the home page (i.e. index).

All you need to do if you want to try to reproduce it is to add this to BitBucket (or other git repository - not sure if it is specific to BitBucket or not), make sure to link your project for continuous deployment, make a change, commit and upload your changes. This is the part that fails for me.

If you then use WebDeploy in VS, it then works.

Don't forget, you have to add the StorageConnectionString in the appSettings section in both project and set it to the relevant Azure Storage.

Thanks.

1
Can you create a minimal solution which repros this issue and publish it to github and share the github link?Zain Rizvi
Hi Zain, thanks for offering to help. It is already a minimal solution as I'm just learning about Azure from the MS Virtual Academy. I build a simple asp.net mvc and added very basic Azure info to it i.e. add a number to a table and while I've changed all connection strings, I'm a little bit concern publishing it on GitHub as I'm not 100% sure that I've removed everything that could potentially jeopardize my azure account. Every time I think I'm done, I find another section I should have removed, so as I said I'm a bit concerned releasing this.Thierry

1 Answers

1
votes

Do you have a plan to deploy your application to Cloud Services? If so, using CloudConfigurationManager makes sense, however, if you are not going to be looking for application settings in the RuntimeEnvironment it's better to just use the ConfiguratoinManager which is available from the base .NET Runtime.