Restart Web/Api-App on Azure programmatically - azure

How can I restart Web-Apps and API-Apps on Azure programmatically?
(I'd like to call it from another API-App within the same App service plan.)

There's also the "Microsoft Azure Management Libraries" Nuget that allows you to work with Azure services from inside of applications.
See this page for an example on how to create new web sites from inside of an Azure Web site. Restarting web services work in a similar way to creating new services. See this page for a list of available web site related methods.
Also, for authenticating is used certificate base authentication, see this page for more details on that.
Bellow is a short command line program that will restart all websites in all the webspaces you got in your Azure subscription. It works kinda like an iisreset for Azure Web Sites.
The code is based on samples taken from the links earlier mentioned:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.WindowsAzure.Management.WebSites;
using Microsoft.WindowsAzure;
using System.Security.Cryptography.X509Certificates;
using Microsoft.WindowsAzure.Management.WebSites.Models;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var subscriptionId = "[INSERT_YOUR_SUBSCRIPTION_ID_HERE]";
var cred = new CertificateCloudCredentials(subscriptionId, GetCertificate());
var client = new WebSiteManagementClient(cred);
WebSpacesListResponse webspaces = client.WebSpaces.List();
webspaces.Select(p =>
{
Console.WriteLine("Processing webspace {0}", p.Name);
WebSpacesListWebSitesResponse websitesInWebspace = client.WebSpaces.ListWebSites(p.Name,
new WebSiteListParameters()
{
});
websitesInWebspace.Select(o =>
{
Console.Write(" - Restarting {0} ... ", o.Name);
OperationResponse operation = client.WebSites.Restart(p.Name, o.Name);
Console.WriteLine(operation.StatusCode.ToString());
return o;
}).ToArray();
return p;
}).ToArray();
if(System.Diagnostics.Debugger.IsAttached)
{
Console.WriteLine("Press anykey to exit");
Console.Read();
}
}
private static X509Certificate2 GetCertificate()
{
string certPath = Environment.CurrentDirectory + "\\" + "[NAME_OF_PFX_CERTIFICATE]";
var x509Cert = new X509Certificate2(certPath,"[PASSWORD_FOR_PFX_CERTIFICATE]");
return x509Cert;
}
}
}
Another alternative, if you can't find the function you need from the above mentioned library, you can also run powershell commands programmatically from inside of your application. You most likely will need to move, the application that is supposed to run these cmdlets, to a virtual machine to be able to load the needed powershell modules. See this page for more information on running powershell cmdlets programmatically.

You can use Powershell to do this. The relevant commands are:
Start-AzureWebsite -Name “xxxx”
Stop-AzureWebsite -Name “xxxx”
You can find help on these commands at the following links:
https://msdn.microsoft.com/en-us/library/azure/dn495288.aspx
https://msdn.microsoft.com/en-us/library/azure/dn495185.aspx

I think handling the base REST API is much better option. The Azure SDK changes quite a lot and lacks good documentation.
Here is an up-to-date sample code:
https://github.com/davidebbo/AzureWebsitesSamples/
You can adapt it to your needs.

Related

Asynchronous HttpClient calls not shown as dependency in Azure App insights for App service automatically

I am new to Azure app insights and want to know why are Asynchronous HttpClient calls not shown as dependency automatically in Azure App insights for App service.
Also, what configuration changes or code changes should I make in ASP.NET project for tracking http dependencies ?
When I refer documentation it says "A dependency is a component that is called by your application. It's typically a service called using HTTP, or a database, or a file system. Application Insights measures the duration of dependency calls, whether its failing or not, along with additional information like name of dependency and so on. You can investigate specific dependency calls, and correlate them to requests and exceptions."
You can use the below example of code to track http dependency automatically
using Microsoft.ApplicationInsights;
using Microsoft.ApplicationInsights.DependencyCollector;
using Microsoft.ApplicationInsights.Extensibility;
using System.Net.Http;
using System.Threading.Tasks;
namespace ConsoleApp
{
class Program
{
static void Main(string[] args)
{
TelemetryConfiguration configuration = TelemetryConfiguration.CreateDefault();
configuration.InstrumentationKey = "removed";
configuration.TelemetryInitializers.Add(new HttpDependenciesParsingTelemetryInitializer());
var telemetryClient = new TelemetryClient(configuration);
using (InitializeDependencyTracking(configuration))
{
// run app...
telemetryClient.TrackTrace("Hello World!");
using (var httpClient = new HttpClient())
{
// Http dependency is automatically tracked!
httpClient.GetAsync("https://microsoft.com").Wait();
}
}
// before exit, flush the remaining data
telemetryClient.Flush();
// flush is not blocking when not using InMemoryChannel so wait a bit. There is an active issue regarding the need for `Sleep`/`Delay`
// which is tracked here: https://github.com/microsoft/ApplicationInsights-dotnet/issues/407
Task.Delay(5000).Wait();
}
static DependencyTrackingTelemetryModule InitializeDependencyTracking(TelemetryConfiguration configuration)
{
var module = new DependencyTrackingTelemetryModule();
// prevent Correlation Id to be sent to certain endpoints. You may add other domains as needed.
module.ExcludeComponentCorrelationHttpHeadersOnDomains.Add("core.windows.net");
module.ExcludeComponentCorrelationHttpHeadersOnDomains.Add("core.chinacloudapi.cn");
module.ExcludeComponentCorrelationHttpHeadersOnDomains.Add("core.cloudapi.de");
module.ExcludeComponentCorrelationHttpHeadersOnDomains.Add("core.usgovcloudapi.net");
module.ExcludeComponentCorrelationHttpHeadersOnDomains.Add("localhost");
module.ExcludeComponentCorrelationHttpHeadersOnDomains.Add("127.0.0.1");
// enable known dependency tracking, note that in future versions, we will extend this list.
// please check default settings in https://github.com/microsoft/ApplicationInsights-dotnet-server/blob/develop/WEB/Src/DependencyCollector/DependencyCollector/ApplicationInsights.config.install.xdt
module.IncludeDiagnosticSourceActivities.Add("Microsoft.Azure.ServiceBus");
module.IncludeDiagnosticSourceActivities.Add("Microsoft.Azure.EventHubs");
// initialize the module
module.Initialize(configuration);
return module;
}
}
}
NOTE: -
Based on the MSDOC Azure Monitor Application Insights Agent currently supports ASP.NET 4.x only.
For more information please refer the below links:
MS DOC: Application Insights for .NET console applications(Source code) & Automatically dependency tracking
GitHub : LINK1 & LINK2

Xamarin.Android Cannot pull table from Azure database in Android 10 Q

I did read that because lack of support for Netcore 2.1 the
myItemsList = await App.MobileServiceAndroid.GetTable<MyTable>().ToListAsync();
does not currently work on Android, and there is a workaround to pass an HttpClientHandler() in the constructor of the MobileServiceClient, and so I did like this:
public static MobileServiceClient MobileServiceAndroid =
new MobileServiceClient(AppConstants.AZURE_PRODUCTION_WEB_API_URL, new HttpClientHandler());
But this is incomplete,its still not working, what exactly do I have to do to make this work, any guidance is much appreciated.
From my understanding, you are using a Forms/PCL project whereas the other solution was implementing this code inside their Android project.
For you, once you add using Xamarin.Android.Net; to the class, you should be able to just do this:
public static MobileServiceClient MobileServiceAndroid =
new MobileServiceClient(AppConstants.AZURE_PRODUCTION_WEB_API_URL, new AndroidClientHandler());
Most likely you might have issues getting that using statement, for that you will have to follow steps shown here, or customized for you in the following steps:
Add the Xamarin Forms project to all your projects.
Create an interface ICustomClientHandler in the Core project
using System;
using System.Net.Http;
namespace Test
{
public interface ICustomClientHandler
{
HttpClientHandler GetHandler();
}
}
Then create a CustomClientHandler in the Droid project, which will be the Android part of the dependency service that will help you retrieve the native AndroidClientHandler
using System.Net.Http;
using Xamarin.Android.Net;
using System.Runtime.CompilerServices;
using Xamarin.Forms;
using Test;
[assembly: Xamarin.Forms.Dependency(typeof(Test.Droid.CustomClientHandler))]
namespace Test.Droid
{
public class CustomClientHandler : ICustomClientHandler
{
public HttpClientHandler GetHandler()
{
return new AndroidClientHandler();
}
}
}
Implement an iOS version as well in a similar way, but it will instead return new HttpClientHandler();
Finally, use the code as shown, in your Core project:
var clientHandler = DependencyService.Get<ICustomClientHandler>().GetHandler();
public static MobileServiceClient MobileServiceAndroid =
new MobileServiceClient(AppConstants.AZURE_PRODUCTION_WEB_API_URL, clientHandler);

Azure WebJob runtime unable to map virtual key using MapVirtualKey (user32.dll)

.Net Console Application works just fine until it is uploaded as Azure WebJob to Azure website. Code to replicate:
using System;
using System.Runtime.InteropServices;
using System.Windows.Input;
namespace ConsoleApplication2
{
class Program
{
[DllImport("user32.dll")]
private static extern uint MapVirtualKey(uint uCode, uint uMapType);
static void Main()
{
foreach (uint c in new uint[] {18, 31})
{
var mapped = (int) MapVirtualKey(c, 1);
Console.WriteLine($"{mapped} : {KeyInterop.KeyFromVirtualKey(mapped)}");
}
}
}
}
Expected output:
69 : E
83 : S
Actual output:
-1073741790 : None
-1073741790 : None
Not sure where to go from here. does it mean that access is denied for this api call?
The reason this doesn't work is that the MapVirtualKey API is blocked by the Azure Web App sandbox. You can learn more about the sandbox on https://github.com/projectkudu/kudu/wiki/Azure-Web-App-sandbox. See in particular this paragraph:
For the sake of radical attack surface area reduction, the sandbox prevents almost all of the Win32k.sys APIs from being called, which practically means that most of User32/GDI32 system calls are blocked. For most applications this is not an issue since most Azure Web Apps do not require access to Windows UI functionality (they are web applications after all).

Azure WebJobs Connection Strings configuration ( AzureWebJobsDashboard?? )

I'm trying to work with Azure Webjobs, I understand the way its works but I don't understand why I need to use two connection strings, one is for the queue for holding the messages but
why there is another one called "AzureWebJobsDashboard" ?
What its purpose?
And where I get this connection string from ?
At the moment I have one Web App and one Webjob at the same solution, I'm experiment only locally ( without publishing anything ), the one thing I got up in the cloud is the Storage account that holds the queue.
I even try to put the same connection string in both places ( AzureWebJobsDashboard,AzureWebJobsStorage) but its throw exception :
"Cannot bind parameter 'log' when using this trigger."
Thank you.
There are two connection strings because the WebJobs SDK writes some logs in the storage account. It gives you the possibility of having one storage account just for data (AzureWebJobsStorage) and the another one for logs (AzureWebJobsDashboard). They can be the same. Also, you need two of them because you can have multiple job hosts using different data accounts but sending logs to the same dashboard.
The error you are getting is not related to the connection strings but to one of the functions in your code. One of them has a log parameter that is not of the right type. Can you share the code?
Okay, anyone coming here looking for an actual answer of "where do I get the ConnectionString from"... here you go.
On the new Azure portal, you should have a Storage Account resource; mine starts with "portalvhds" followed by a bunch of alphanumerics. Click that so see a resource Dashboard on the right, followed immediately by a Settings window. Look for the Keys submenu under General -- click that. The whole connection string is there (actually there are two, Primary and Secondary; I don't currently understand the difference, but let's go with Primary, shall we?).
Copy and paste that in your App.config file on the connectionString attribute of the AzureWebJobsDashboard and AzureWebJobsStorage items. This presumes for your environment you only have one Storage Account, and so you want that same storage to be used for data and logs.
I tried this, and at least the WebJob ran without throwing an error.
#RayHAz - Expanding upon your above answer (thanks)...
I tried this https://learn.microsoft.com/en-us/azure/app-service/webjobs-sdk-get-started
but in .Net Core 2.1, was getting exceptions about how it couldn't find the connection string.
Long story short, I ended up with the following, which worked for me:
appsettings.json, in a .Net Core 2.1 Console app:
{
"ConnectionStrings": {
"AzureWebJobsStorage": "---your Azure storage connection string here---",
"AzureWebJobsDashboard":"---the same connectionstring---"
}
}
... and my Program.cs file...
using System;
using System.IO;
using Microsoft.Azure.WebJobs;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
namespace YourWebJobConsoleAppProjectNamespaceHere
{
public class Program
{
public static IConfiguration Configuration;
static void Main(string[] args)
{
var builder = new ConfigurationBuilder()
.SetBasePath(Path.Combine(AppContext.BaseDirectory))
.AddJsonFile("appsettings.json", true);
Configuration = builder.Build();
var azureWebJobsStorageConnectionString = Configuration.GetConnectionString("AzureWebJobsStorage");
var azureWebJobsDashboardConnectionString = Configuration.GetConnectionString("AzureWebJobsDashboard");
var config = new JobHostConfiguration
{
DashboardConnectionString = azureWebJobsDashboardConnectionString,
StorageConnectionString = azureWebJobsStorageConnectionString
};
var loggerFactory = new LoggerFactory();
config.LoggerFactory = loggerFactory.AddConsole();
var host = new JobHost(config);
host.RunAndBlock();
}
}
}

Unable to create Website using powershell in window service

I Want to create a website in IIS using powershell script.I write this code in a window service.
protected override void OnStart(string[] args)
{
string sitename = "rajesh";
//To create a New site
//Powershell script
string script = "cd\\\n" + "import-Module WebAdministration \n" + "IIS:\n" + "New-item iis:\\Sites\\rajesh -PhysicalPath C:\\inetpub\\wwwroot\test -bindings #{Protocol='http';bindingInformation='*:8080:" + sitename + "'}" + "\n add-content C:\\Windows\\System32\\drivers\\etc\\Hosts '127.0.0.1 " + sitename + "'";
string s = RunScript(script);
}
private static string RunScript(string scriptText)
{
Runspace runspace = RunspaceFactory.CreateRunspace();
runspace.Open();
Pipeline pipeline = runspace.CreatePipeline();
pipeline.Commands.AddScript(scriptText);
pipeline.Commands.Add("Out-String");
Collection<PSObject> results = pipeline.Invoke();
runspace.Close();
StringBuilder stringBuilder = new StringBuilder();
foreach (PSObject obj in results)
{
stringBuilder.AppendLine(obj.ToString());
}
return stringBuilder.ToString();
}
But when i try to start this window service in services listing...It throws an error.. The services on locat computer start and stopped..... When i change the powershell script to Create a folder or some small task then this window service is working but when i try to create a website through this powershell..it throws an error and window service can't be started.This powershell script is working in powershell.But not in window service..
The error produced would be helpful.
Sitename isn't a variable either, is that atypo here or in the code?
You could try replacing the \n with ; as well, powershell doesn't use that as new line, though i guess the C# is.
There's a couple of things to note here and I think you maybe don't understand some aspects of Windows Services:
OnStart is not the place to be putting any kind of logic. This event is there so you can initialise the service. For example starting a background worker thread that would run the main logic of the service and respond to external requests. For example - starting a TCP listener or initialising .NET Remoting or WCF.
OnStart is only called once when the service starts.
OnStart must return within 30 seconds although your initialisation code can request additional time.
You're calling out to PowerShell and the WebAdministration add-in to create websites. Whilst this is doable, it's clunky, perhaps you should consider calling directly into the IIS7 Managed API's:
Microsoft.Web.Administration Namespace
Here's an example of creating a site using the managed API's:
using (ServerManager serverManager = new ServerManager())
{
Site site = serverManager.Sites.Add("My Web Site", "C:\\inetpub\\wwwroot\test", 80);
site.Bindings.Clear();
site.Bindings.Add("*:8080:", "http");
serverManager.CommitChanges();
}
It should also be noted that any configuration tasks performed on IIS require that the account doing this have elevated privileges i.e. be an Administrator or if it's a service run under the SYSTEM account.

Resources