Windows Azure creating virtual directory to local storage - azure

I need a help with creating virtual directory pointing to local storage in Windows Azure (production environment). I can set up a virtual directory manually but it is being erased every time Azure is restarted. The clue is to create the virtual directory via config file when I upload a package of my project on Azure. The question is how to create such directory so that it is pointing to local storage.
Thx in advance for any suggestions.
Best Regards,
Darek

I suggest you create the virtual directory by interacting with IIS in the WebRole's OnStart method:
public class WebRole : RoleEntryPoint
{
public override bool OnStart()
{
// Connect to the IIS site.
using (var manager = new Microsoft.Web.Administration.ServerManager())
{
var localResourcePath = RoleEnvironment.GetLocalResource("MyResource").RootPath;
// Add to the root application.
var rootSite = manager.Sites[RoleEnvironment.CurrentRoleInstance.Id + "_Web"];
var rootApplication = rootSite.Applications["/"];
rootApplication.VirtualDirectories.Add("/myVdir", localResourcePath);
// Save
manager.CommitChanges();
}
...
}
}
If I'm right you'll need to set the execution context to elevated for this to work. You can do this in the ServiceDefintion.csdef:
<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="MyProject" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition" schemaVersion="2012-05.1.7">
<WebRole name="MyRole" vmsize="Small" enableNativeCodeExecution="true">
<Runtime executionContext="elevated" />
...
</WebRole>
</ServiceDefinition>
Note: You'll need to reference Microsoft.Web.Administration.dll (C:\Windows\System32\inetsrv)

Related

How do I add a service stack license to a .NET core project?

For my service stack license I am used to adding a web config entry
<add key="servicestack:license" ... />
How do I achieve a similar effect in ServiceStack.Core since there is no web config?
The license key can be registered using any of the options listed at: https://servicestack.net/download#register
So while there's no Web.config you can use any of the other 3 options like registering the SERVICESTACK_LICENSE Environment Variable.
Also whilst .NET Core doesn't need to use Web.config or App.config you can still use one in .NET Core in ServiceStack for storing any <appSettings>, e.g:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="servicestack:license" value="{LicenseKey}" />
</appSettings>
</configuration>
But you'll need to register the license key explicitly from the AppSettings with:
using ServiceStack;
public class AppHost : AppHostBase
{
public AppHost()
: base("Service Name", typeof(MyServices).GetAssembly())
{
var licenseKeyText = AppSettings.GetString("servicestack:license");
Licensing.RegisterLicense(licenseKeyText);
}
public override void Configure(Container container)
{
}
}
Or if you don't want to use Web.config you can use any other AppSettings options.

NLog with DNX Core 5.0

I am attempting to implement NLog logging using ASP.Net 5 and MVC 6. Be default, both DNX 451 and DNX Core 50 are included in the project template.
I am attempting to implement NLog Logging by following the example here.
However, in the sample app, there is the following line -
#if !DNXCORE50
factory.AddNLog(new global::NLog.LogFactory());
#endif
And if I run the app, this line never gets hit because the mvc application has dnx core 50 installed by default.
Is there any loggers that are available for DNX Core 50? If not, what purpose does dnx core serve in the default mvc app - is it actually needed?
Edit: If I remove the #if !DNXCORE50.... line above, I get a the following error -
DNX Core 5.0 error - The type or namespace name 'NLog' could not be found in the global namespace'
DNX Core 5.0 is only necessary if you want the cloud-optimized cross-platform version of the .Net framework; if you still plan on using the MVC app within only a Windows environment, you can remove your dnxcore50 framework reference from your project.json.
NLog for .NET Core (DNX environment) is currently available in version 4.4.0-alpha1.
Steps:
Create NLog.config
<?xml version="1.0" encoding="utf-8" ?>
<targets>
<target xsi:type="ColoredConsole" name="ToConsole" />
</targets>
<rules>
<logger name="*" minlevel="Info" writeTo="ToConsole" />
</rules>
Load and parse configuration
private static ILogger _logger;
public static void LoggerSetup()
{
var reader = XmlReader.Create("NLog.config");
var config = new XmlLoggingConfiguration(reader, null); //filename is not required.
LogManager.Configuration = config;
_logger = LogManager.GetCurrentClassLogger();
}
public static void Main(string[] args)
{
LoggerSetup();
// Log anything you want
}
When dealing with the MVC tooling in MVC6 (dnx stuff), the answer to this is very fluid.
In order to get NLog to work with my web app, I had to do a couple steps:
-> Big thanks to two NLog discussions(here and here)
I just needed to add the configuration setup in my Startup.cs's constructor:
public Startup(IHostingEnvironment env)
{
// Set up configuration sources.
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddEnvironmentVariables();
// Set up logging configuration
// from: https://github.com/NLog/NLog/issues/641
// and: https://github.com/NLog/NLog/issues/1172
var reader = XmlTextReader.Create(File.OpenRead(Path.Combine(builder.GetBasePath(),"NLog.config"))); //stream preferred above byte[] / string.
LogManager.Configuration = new XmlLoggingConfiguration(reader, null); //filename is not required.
log.Info("NLogger starting");
Configuration = builder.Build();
}
I consider this a bit of a stop-gap as Microsoft is introducing a new Logging interface (that I hope will end up being like SLF4J.org is in Java). Unfortunately, documentation on that is a bit thin at the time I'm writing this. NLog is working diligently on getting themselves an implementation of the new dnx ILoggingProvider interface.
Additional information about my project setup
My NLog.config file is located in the project root folder, next to
the project.json and appsettings.json. I had to do a little digging
inside AddJsonFile() to see how they handled pathing.
I used yeoman.io and their aspnet generator to set up the web project.
Version of NLog, thanks to Lukasz Pyrzyk above:
"NLog": "4.4.0-alpha1"

Issue accessing service setting from an executable running as a start up task

I'm relatively new to Azure development and need some help overcoming the following predicament:
I have an executable that I need to run as part of my Azure service startup. The executable needs access to one of the service's application settings.
So I added the following to my csdef (the batch script just runs the executable with output redirected to a file):
<Startup>
<Task commandLine="StartupTask.cmd" executionContext="elevated" taskType="background">
<Environment>
<Variable name="Var">
<RoleInstanceValue
xpath="/RoleEnvironment/CurrentInstance/ConfigurationSettings/ConfigurationSetting[#name='SomeAppSetting']/#value" />
</Variable>
</Environment>
</Task>
</Startup>
Adding the task caused the deployment to fail and after much hair tearing I realized it was because SomeAppSetting value was too long (see http://blogs.msdn.com/b/cie/archive/2013/07/30/windows-azure-role-recycling-due-to-setting-more-than-256-character-in-environmental-variable-through-azure-start-up-task.aspx) and now I'm at a loss of what to do.
Are the following possible:
1. Accessing the role environment from inside the executable somehow?
2. Passing the setting value to the script as a parameter?
Thanks in advance for any tips!
One option would be to move the app setting from the service configuration to blob storage from where it is accessible to both the startup task and the running service.
You can load the RoleEnvironment information in a PowerShell script (which you load in the startup task) which will let you access your ServiceConfiguration settings:
[Reflection.Assembly]::LoadWithPartialName("Microsoft.WindowsAzure.ServiceRuntime")
$mySetting = [Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment]::GetConfigurationSettingValue("MySetting")
if($mySetting -eq "True"){ .....}
In my ServiceConfiguration (.cscfg) I have a setting called MySettig which is True/False.

Cannot inject dependencies to Azure WorkerRole object using Spring.NET

I have moderate experience in developing web applications using spring.net 4.0 , nhibernate 3.0 for ASP.net based web applications. Recently I ran into a situation where I needed to use spring.net to inject my service dependencies which belong to the WorkerRole class. I created the app.config file as I normally did with the web.config files on for spring. Here it is for clarity. (I have excluded the root nodes)
<configSections>
<sectionGroup name="spring">
<section name="context" type="Spring.Context.Support.WebContextHandler, Spring.Web" requirePermission="false" />
<section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" requirePermission="false" />
<section name="parsers" type="Spring.Context.Support.NamespaceParsersSectionHandler, Spring.Core" />
</sectionGroup>
</configSections>
<spring>
<context>
<!-- Application services and data access that has been previously developed and tested-->
<resource uri="assembly://DataAccess/data-access-config.xml" />
<resource uri="assembly://Services/service-config.xml" />
<resource uri="AOP.xml" />
<resource uri="DI.xml"/>
</context>
<parsers>
<parser type="Spring.Data.Config.DatabaseNamespaceParser, Spring.Data" />
<parser type="Spring.Transaction.Config.TxNamespaceParser, Spring.Data" />
<parser type="Spring.Aop.Config.AopNamespaceParser, Spring.Aop" />
</parsers>
</spring>
Similarly Here's the AOP.xml
<object id="FilterServiceProxy" type="Spring.Aop.Framework.ProxyFactoryObject, Spring.Aop">
<property name="proxyInterfaces" value="Domain.IFilterService"/>
<property name="target" ref="FilterService"/>
<property name="interceptorNames">
<list>
<value>UnhandledExceptionThrowsAdvice</value>
<value>PerformanceLoggingAroundAdvice</value>
</list>
</property>
</object>
</objects>
and the DI.xml
<object type="FilterMt.WorkerRole, FilterMt" >
<property name="FilterMtService1" ref="FilterServiceProxy"/>
</object>
However, I was unable to inject any dependencies into the worker role. Can someone please let me know what I am doing wrong here ? Is there a different way to configure Spring.net DI for windows azure applications ?
I don't get any configuration errors but I see that the dependencies have not been injected because the property object to which I've tried injection, remains null.
Based on my experience, you cannot inject anything into your WorkerRole class (the class that implements RoleEntryPoint). What I do, so far with Unity (I also built my own helper for Unity to help me inject Azure settings), is that I have my own infrastructure that runs and is built by Unity, but I create it in the code for the worker role.
For example, I initialize the dependency container in my OnStart() method of RoleEntry point, where I resolve anything I need. Then in my Run() method I call a method on my resolved dependency.
Here is a quick, stripped off version of my RoleEntryPoint's implementation:
public class WorkerRole : RoleEntryPoint
{
private UnityServiceHost _serviceHost;
private UnityContainer _container;
public override void Run()
{
// This is a sample worker implementation. Replace with your logic.
Trace.WriteLine("FIB.Worker entry point called", "Information");
using (this._container = new UnityContainer())
{
this._container.LoadConfiguration();
IWorker someWorker = this._container.Resolve<IWorker>();
someWorker.Start();
IWorker otherWorker = this._container.Resolve<IWorker>("otherWorker");
otherWorker.Start();
while (true)
{
// sleep 30 minutes. we don't really need to do anything here.
Thread.Sleep(1800000);
Trace.WriteLine("Working", "Information");
}
}
}
public override bool OnStart()
{
// Set the maximum number of concurrent connections
ServicePointManager.DefaultConnectionLimit = 12;
// For information on handling configuration changes
// see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357.
this.CreateServiceHost();
return base.OnStart();
}
public override void OnStop()
{
this._serviceHost.Close(TimeSpan.FromSeconds(30));
base.OnStop();
}
private void CreateServiceHost()
{
this._serviceHost = new UnityServiceHost(typeof(MyService));
var binding = new NetTcpBinding(SecurityMode.None);
RoleInstanceEndpoint externalEndPoint =
RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["ServiceEndpoint"];
string endpoint = String.Format(
"net.tcp://{0}/MyService", externalEndPoint.IPEndpoint);
this._serviceHost.AddServiceEndpoint(typeof(IMyService), binding, endpoint);
this._serviceHost.Open();
}
As you can see, my own logic is IWorker interface and I can have as many implementations as I want, and I instiate them in my Run() method. What I do more is to have a WCF Service, again entirely configured via DI with Unity. Here is my IWorker interface:
public interface IWorker : IDisposable
{
void Start();
void Stop();
void DoWork();
}
And that's it. I don't have any "hard" dependencies in my WorkerRole, just the Unity Container. And I have very complex DIs in my two workers, everything works pretty well.
The reason why you can't interfere directly with your WorkerRole.cs class, is that it is being instantiated by the Windows Azure infrastructure, and not by your own infrastructure. You have to accept that, and built your infrastructure within the WorkerRole appropriate methods. And do not forget that you must never quit/break/return/exit the Run() method. Doing so will flag Windows Azure infrastructure that there is something wrong with your code and will trigger role recycling.
Hope this helps.
I know this is an old question, but I'm going through the same learning curve and would like to share my findings for someone who struggles to understand the mechanics.
The reason you can't access DI in your worker role class is because this is run in a separate process in the OS, outside of IIS. Think of your WebRole class as being run in a Windows Service.
I've made a little experiment with my MVC web-site and WebRole class:
public class WebRole : RoleEntryPoint
{
public override void Run()
{
while (true)
{
Thread.Sleep(10000);
WriteToLogFile("Web Role Run: run, Forest, RUN!");
}
}
private static void WriteToLogFile(string text)
{
var file = new System.IO.StreamWriter("D:\\tmp\\webRole.txt", true); // might want to change the filename
var message = string.Format("{0} | {1}", DateTime.UtcNow, text);
file.WriteLine(message);
file.Close();
}
}
This would write to a file a new string every 10 seconds (or so). Now start your Azure site in debugging mode, make sure the site deployed to Azure emulator and the debugger in VS has started. Check that the site is running and check that WebRole is writing to the file in question.
Now stop the IIS Express (or IIS if you are running it in full blown installation) without stopping the VS debugger. All operations in your web-site are stopped now. But if you check your temp file, the process is still running and you still get new lines added every 10 seconds. Until you stop the debugger.
So whatever you have loaded in memory of web-application is inside of the IIS and not available inside of Worker Role. And you need to re-configure your DI and other services from the scratch.
Hope this helps someone to better understand the basics.

Delay making virtual machine role available until startup tasks complete

Is it possible delay making a virtual machine role available untill startup tasks complete?
I have a few tasks I need to complete on virtual machine start before the machine can safely be added to the load balancer. Is there a way to do this?
Found the solution. In the VM Role Startup windows service I can handle the RoleEnvironment.StatusCheck event. I can then call SetBusy() to tell prevent the instance being available in the load balancer.
private void RoleEnvironmentStatusCheck(object sender, RoleInstanceStatusCheckEventArgs e)
{
if (this.busy)
{
e.SetBusy();
}
statusCheckWaitHandle.Set();
}
I believe that setting the taskType attribute to simple will make the Role wait for the task completion before actually starting:
<ServiceDefinition name="MyService" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
<WebRole name="WebRole1">
<Startup>
<Task commandLine="Startup.cmd" executionContext="limited" taskType="simple">
</Task>
</Startup>
</WebRole>
</ServiceDefinition>

Resources