I want to access my windows Azure Data Cache from my Role Entry StartUp routine. However I keep getting this error:
{"ErrorCode:SubStatus:Server collection cannot be empty."}
However when I do the same from within my Controller class it loads the Data Cache fine and I can go ahead and do things with it.
Is there anything special for the Role Entry class that I have to do to access the Data Cache prior to my application starting?
Or can't I access the Cache in the Role StartUp ?
Cheers
Starting with Azure SDK 1.3, there is a major change - the Full IIS mode. Read this blog post to get full undertanding of full IIS and what is it.
In short - your RoleEntryPoint descendant (where your OnStart method is being executed) lives in whole another AppDomain (and process actually - WaIISHost.exe), while your actual web application just lives in IIS (w3wp.exe). That's why there is no way to do something in OnStart() that would affect your web applicatin or that would be able to directly read your web.config.
If you do read Azure Data Cache in OnStart to do some preload of data for the web application, just do in your Global.asax's Application_Start() event handler.
If you need to read Azure Data Cache in OnStart for reason's specific to the RoleEntryPoint, you have to load the configuration from web.config. Web.config is placed in "./bin/web.config" relative to your AppRoot folder. (there are two copies of your application when you use WebRoles with full IIS - one lives in AppRoot and one lives in SitesRoot).
Hope this helps!
WebRole's OnStart probably does not use your web.config where you probably have specified server names and access keys for your AppFabric DataCache provider.
I would try manually instrumenting the server connection configuration.
Related
I am using IIS7.5 to force my web app to load automatically (startMode="AlwaysRunning"), and I now want to preload my cache data. I am a bit confused though because two approaches seem identical:
use Application_Start in global.asax
use serviceAutoStartProviders in IIS config files
They seem rather redundant and doing the same thing. If they are, I guess I would rather use Application_Start than create code dependencies in IIS configuration files. Any advice?
The Application_Start in the global.asax is fired when the application receives it's first request (first user or autostart) so it is not used to start the site.
Use serviceAutoStartProviders to start
http://www.asp.net/whitepapers/aspnet4#0.2__Toc253429241
The IIS Application Warm-Up Module is easier to use
http://www.iis.net/learn/get-started/whats-new-in-iis-8/iis-80-application-initialization
In an Azure web role, I want to retrieve the date/time when an assembly was build. I've seen a few tricks to do this by retrieving the linker timestamp from the PE header, but this requires you to read the Assembly.Location which doesn't seem to work in a Azure project. I get this exception:
NotSupportedException - The invoked member is not supported in a dynamic assembly
Perhaps there's a better way of getting this info. Perhaps I can grab the date/time when the Web Role was deployed? That would work for me as well.
Thanks for any help.
You are asking two separate things. It is very much possible that the time when code was compiled/build could be far different then when the role was deployed. So you may get the same date/time and may not, there is no guarantee unless you control build and deploy same time.
If your objective is to know when the role was deployed, you can add this date/time in multiple location and retrieve it in your Role specific code directly. I am not sure if there is a way to get the deployment time from the role and will look deep later.
Here are few suggestions comes in my mind immediately:
Create a "String" setting in your Service Configuration and read it in your Role specific Code. Keep in mind you can not get Service Configuration settings directly in Web Role specific W3WP.exe process as these two process run separately and need some extra coding.
You can also add Date/Time to service configuration and access either in Startup task to process further as below:
http://blogs.msdn.com/b/avkashchauhan/archive/2011/11/09/how-to-access-service-configuration-settings-in-windows-azure-startup-task.aspx
You can add Date/Time setting in your App.Config and access it. I have described here:
http://blogs.msdn.com/b/avkashchauhan/archive/2011/10/25/reading-configuration-entries-using-system-configuration-configurationmanager-class-in-a-windows-azure-application.aspx
In the solution you linked to, instead of doing this:
System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
Try doing this:
System.Reflection.Assembly assembly = typeof(AClassInMyAssembly).Assembly;
I'm not sure that will work, but I think it might. If not, you might consider if the Assembly Version would work for your purposes.
I'm using nlog to write log files for debugging purposes. Currently the log file location is set to:
<target
name="file"
xsi:type="File"
fileName="${specialfolder:folder=LocalApplicationData}/x/y.log"
but this is resulting in a the file being written to c:\x\y.log, not %windir%\ServiceProfiles\NetworkService\AppData\Local\x\y.log, as I would expect with asp.net/IIS running under NETWORK SERVICE account.
Checking the value for Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) from the web application yields an empty/null string, which at least explains why my logs are ending up in the root.
So really two questions:
We have services written and running under NETWORK SERVICE account that resolve this path correctly. What's special about asp.net/IIS such that no value is returned for this special folder?
Where is a safe and sensible place to write a log to, given that my asp.net process is running under NETWORK SERVICE account?
If my knowledge is correct, the problem is that IIS doesn't load the profile for the user Network Service.
You could adjust this setting in the properties of the application pool (source)
If you set this parameter to true, the call to Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) should return a correct result.
See also:
Wrong path returned by Environment.GetFolderPath(Environment.SpecialFolder.ApplicationFolder) under IIS6 WebService
http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/890fa85a-b11a-4fbe-a333-cbe69abd72a7/
You can now load the user profile of the application pool identity
If it does not work, I would recommend to create a folder with the appropriate rights for the service account for logging purposes.
I am currently running a WCF service on an AppFabric server and my application needs to load a the web.config file dynamically to retrieve custom configuration sections.
On my development machine I can just load the configuration like this:
WebConfigurationManager.OpenMappedWebConfiguration(webMappedFile, virtualPath);
But on the test machine (AppFabric server) I am getting an exception and it seems that I need to specify a third parameter which is actually the site the web application is running on:
WebConfigurationManager.OpenMappedWebConfiguration(webMappedFile, virtualPath, "MySite");
So I tried to hard code it and it worked. Anyway this is not acceptable, so I need to dynamically provide the site to the WebConfigurationManager because I do not on which site the service will be running in the future. Do anybody knows how to achieve that?
Thanks.
If you are running this code as part of handling a request you could use:
Request.ServerVariables("server_name")
see: http://msdn.microsoft.com/en-us/library/ms525396(VS.90).aspx
Edit based on your comment
The parameter that you need is the Site Name, not the machine name, your code be running on many machines. If the code is running somewhere where it no longer knows that it is on a web site, then it is difficult for it to get the name of the web site that it is running on.
You then have two options:
Send the name as a parameter from a layer that has httpconext
Not sure if this will work: but you could try adding a reference to system.web to your project. It may compile, but you could get a null reference exception when you run it. Probably worth a try.
How about Server.MachineName
I have developed my own custom provider for the health monitoring; however, I use parameters in the constructor and this is not allowed when using the health monitoring from the web.config file.
Does anyone know if I can turn on/off the monitoring and have it watch properly through code (possibly in my global.asax file on application startup).
Or, is it possible for me to create my own watcher that will do the same thing as the health monitor.
Or, finally - can I just pass variables from the web.config setup (i'm not familiar with the public token part of the provider type declaration).
Thanks in advance
I don't know if there are any other better ideas out there... after a lot of reading and trying I ended up using parameters in the provider to pass information into a custom bufferedwebeventprovider.
If you create a custom provider and include the override Initialize(name, config) method then all of your parameters from your web.config file will come through the config param of the Initialize command. Then in the initialize command you can pull them off one by one (and remove them) before passing the rest of the config property to the base.Initialize method.
I used this to save and pull off connection string info, timeouts, custom id's, etc.
I would still like to know anyway to control the health monitoring without having all of the info in the web.config (mostly because this is a database driven website with multiple users and multiple different settings). I'll probably end up having a procedure within the custom provider to check settings and only record entries as needed based on each user's settings.
any other thoughts are very welcome!!