Enable GZip compression for SVG in Azure Web Sites? - azure

I'm trying to enable GZip compress for SVG in an Azure Web Site using web.config transforms without success. Here is what my transform looks like:
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<system.webServer>
<httpCompression>
<staticTypes>
<add mimeType="image/svg+xml" enabled="true" xdt:Transform="Insert" />
</staticTypes>
</httpCompression>
<staticContent xdt:Transform="Insert">
<mimeMap fileExtension=".svg" mimeType="image/svg+xml" />
</staticContent>
</system.webServer>
</configuration>
This should both add the mime type for SVG, which Azure doesn't seem to have, and then enable compression. I've verified the mime type addition works fine, but upon publishing I get an error for the compression elements:
No element in the source document matches
'/configuration/system.webServer/httpCompression/staticTypes'
Removing the compression from the transform and adding it directly to my web.config file removes the error, but I still don't see the compression in the HTTP headers. Here are the response headers:
Accept-Ranges:bytes
Content-Length:23265
Content-Type:image/svg+xml
Date:Mon, 10 Jun 2013 17:19:37 GMT
ETag:"c4e9ec93d765ce1:0"
Last-Modified:Mon, 10 Jun 2013 12:39:41 GMT
Server:Microsoft-IIS/8.0
X-Powered-By:ASP.NET
X-Powered-By:ARR/2.5
X-Powered-By:ASP.NET

Here is how you can enable it in your web.config:
<configuration>
<system.webServer>
<staticContent>
<mimeMap fileExtension=".svg" mimeType="image/svg+xml" />
</staticContent>
<httpCompression>
<staticTypes>
<remove mimeType="*/*" />
<add mimeType="image/svg+xml" enabled="true" />
<add mimeType="*/*" enabled="false" />
</staticTypes>
</httpCompression>
</system.webServer>
</configuration>
The key line is the removal of the catch-all (and later re-add). If you don't have that, then the svg line basically gets ignored since the catch-all is inherited from applicationhost.config, and catches all before it reaches svg line.

Unfortunately it isn't possible to use built-in http compression on Azure Websites for image/xml+svg mime types. You have to change some IIS settings to do that which is possible if you're using Azure Web Roles.
I didn't want to go through that hassle however so I just made a controller in MVC to handle .svg files.
[AttributeRouting.RoutePrefix("static")]
public class ContentController : Controller
{
[GET(#"fonts/{fileName:regex(^[\w-\.]+\.svg$)}")]
[Compress, OutputCache(
Duration = 3600 * 24 * 30,
Location = OutputCacheLocation.Any,
VaryByContentEncoding = "gzip;deflate",
VaryByParam = "fileName")]
public ActionResult SvgFont(string fileName)
{
var path = Server.MapPath("~/Content/fonts/" + fileName);
if (!System.IO.File.Exists(path)) return HttpNotFound();
return File(path, "image/svg+xml");
}
}
public class CompressAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.HttpContext.CompressResult();
}
}
public static class HttpContextExtensions
{
public static bool CompressResult(this HttpContextBase context)
{
var request = context.Request;
var response = context.Response;
if (request == null || response == null) return false;
var filter = response.Filter;
if (filter is GZipStream || filter is DeflateStream) return false;
var acceptEncoding = (request.Headers["Accept-Encoding"] ?? string.Empty).ToLowerInvariant();
if (acceptEncoding.Contains("gzip"))
{
response.Filter = new GZipStream(filter, CompressionMode.Compress);
response.AddHeader("Content-Encoding", "gzip");
response.AppendHeader("Vary", "Content-Encoding");
return true;
}
if (acceptEncoding.Contains("deflate"))
{
response.Filter = new DeflateStream(filter, CompressionMode.Compress);
response.AddHeader("Content-Encoding", "deflate");
response.AppendHeader("Vary", "Content-Encoding");
return true;
}
return false;
}
}
You will also need to add this to your Web.config file so that MVC will handle routes with a .svg extension
<system.webServer>
<handlers>
<add name="StaticMvcHandler" path="static/fonts/*.svg" verb="GET" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>

I have the following configuration entries for an Azure Web-Site:
<system.webServer>
<urlCompression doStaticCompression="true" doDynamicCompression="true" />
</system.webServer>
and
<mimeMap fileExtension=".svg" mimeType="image/svg+xml" />
<!-- Scalable Vector Graphics iPhone, iPad -->
<mimeMap fileExtension=".svgz" mimeType="image/svg+xml" />
I have added the .svgz extension as well (for compressed svg).

The above solution worked for me but I first had to remove the file extension. After that I got the results I was looking for.
<staticContent>
<remove fileExtension=".svg" />
<mimeMap fileExtension=".svg" mimeType="image/svg+xml" />
</staticContent>

Related

Getting error ( POST 500 Internal Server Error) when running Full-Stack Web application in Azure

I have developed a full-stack application with Vue 2, Node , Express and Postgres.
I could deploy the application to Azure , and the system coming up, but when I try to do register user with Register page that I have created , I get " POST … 500 (Internal Server Error) ", **as I have tried with Postman , there is no issue in saving user data with same post controller ** .
Notice that I have set BaseURL to ‘’ in Api.js ( Client ):
import axios from ‘axios’
import store from ‘#/store/store’
export default () => {
return axios.create({
baseURL: ‘’,
headers: {
Authorization: Bearer ${store.state.token}
}
})
}
this is Register controller in /Controller folder :
//Registering user
async register(req, res) {
const hash = bcrypt.hashSync(req.body.password, 10);
try {
const user = await User.create(
Object.assign(req.body, { password: hash })
);
const userJson = user.toJSON();
res.send({
user: userJson,
token: jwtSignUser(userJson),
});
} catch (err) {
res.status(500).send({
error: There is error in registering: ${err},
});
}
},
I have added the following web.config file in dist folder, but it doesn't resolve the issue :
<configuration>
<system.webServer>
<staticContent>
<mimeMap fileExtension="woff" mimeType="application/font-woff" />
<mimeMap fileExtension="woff2" mimeType="application/font-woff" />
</staticContent>
<rewrite>
<rules>
<clear />
<rule name="Redirect to https" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" redirectType="Permanent" appendQueryString="false" />
</rule>
</rules>
</rewrite>
<httpErrors>
<remove statusCode="404" subStatusCode="-1" />
<remove statusCode="500" subStatusCode="-1" />
<error statusCode="404" path="/survey/notfound" responseMode="ExecuteURL" />
<error statusCode="500" path="/survey/error" responseMode="ExecuteURL" />
</httpErrors>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
Could you please let me know how I could resolve the issue .

Not able to upload file on Microsoft azure node

I am trying to upload file from client which is in react to node server which is hosted on Azure web app
Application logs on azure show me this error "This error means that the request sent to the Web server contained an HTTP verb that is not allowed by the configured module handler for the request"
web.config
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<webSocket enabled="false" />
<handlers>
<!-- indicates that the app.js file is a node.js application to be handled by the iisnode module -->
<add name="iisnode" path="server.js" verb="*" modules="iisnode" />
</handlers>
<rewrite>
<rules>
<!-- Don't interfere with requests for logs -->
<rule name="LogFile" patternSyntax="ECMAScript" stopProcessing="true">
<match url="^[a-zA-Z0-9_\-]+\.js\.logs\/\d+\.txt$" />
</rule>
<!-- Don't interfere with requests for node-inspector debugging -->
<rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">
<match url="^server.js\/debug[\/]?" />
</rule>
<!-- First we consider whether the incoming URL matches a physical file in the /public folder -->
<rule name="StaticContent">
<action type="Rewrite" url="public{REQUEST_URI}" />
</rule>
<!-- All other URLs are mapped to the Node.js application entry point -->
<rule name="DynamicContent">
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True" />
</conditions>
<action type="Rewrite" url="server.js" />
</rule>
</rules>
</rewrite>
<!-- You can control how Node is hosted within IIS using the following options -->
<!--<iisnode
node_env="%node_env%"
nodeProcessCommandLine="&quot;%programfiles%\nodejs\node.exe&quot;"
nodeProcessCountPerApplication="1"
maxConcurrentRequestsPerProcess="1024"
maxNamedPipeConnectionRetry="3"
namedPipeConnectionRetryDelay="2000"
maxNamedPipeConnectionPoolSize="512"
maxNamedPipePooledConnectionAge="30000"
asyncCompletionThreadCount="0"
initialRequestBufferSize="4096"
maxRequestBufferSize="65536"
watchedFiles="*.js"
uncFileChangesPollingInterval="5000"
gracefulShutdownTimeout="60000"
loggingEnabled="true"
logDirectoryNameSuffix="logs"
debuggingEnabled="true"
debuggerPortRange="5058-6058"
debuggerPathSegment="debug"
maxLogFileSizeInKB="128"
appendToExistingLog="false"
logFileFlushInterval="5000"
devErrorsEnabled="true"
flushResponse="false"
enableXFF="false"
promoteServerVars=""
/>-->
</system.webServer>
</configuration>
Updated : Code
var express = require("express");
var multer = require('multer');
var router = express.Router();
var logwrite = require('./logwrite');
var storage = multer.diskStorage({
destination: function (req, file, callback) {
callback(null, __dirname);
},
filename: function (req, file, callback) {
callback(null, 'aasasa-' + Date.now());
}
});
var upload = multer({ storage : storage}).single('userPhoto');
router.post("/upload", function(req,res){
// res.send(" we got it !!")
upload(req,res,function(err) {
if(err) {
return res.end("Error uploading file.");
}
else{
res.end("File is uploaded" + __dirname);
}
});
});
module.exports = router;

impersonation in Exchange Web Service (EWS)

I am developing a application for create appointments in my calendar and sending mails on our company's exchange 2013 server using the asp.net 4.0 web application . I get the error as follows:
Unable to cast object of type 'System.Security.Principal.GenericIdentity' to type 'System.Security.Principal.WindowsIdentity'.
My LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref token) function always return 0.
i am Using service.UseDefaultCredentials = true; I just cannot afford to use the username/paasword for every staff who will be using this application. I am thinking there is some problem (rights/permissions/disabled impersonation) issue at the production Web application server (Windows 2008 m/c).
These are the code files:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.Exchange.WebServices.Data;
using Microsoft.Exchange.WebServices.Autodiscover;
using System.Web.Configuration;
//for impersonation before making calls
using System.Security.Principal;
using System.Web.Security;
using System.Runtime.InteropServices;
namespace MvcApplication1
{
public partial class Test1 : System.Web.UI.Page
{
protected ExchangeService service;
//The following Impersonator*** variables are of the exchange account which has been configured to impersonate other users by enabling impersonation on the exchange server as they show at this link: http://msdn.microsoft.com/en-us/library/office/bb204095(v=exchg.140).aspx
protected string ImpersonatorUsername = WebConfigurationManager.AppSettings["ImpersonatorUsername"];
protected string ImpersonatorPassword =WebConfigurationManager.AppSettings["ImpersonatorPassword"];
protected string ImpersonatorDomain = WebConfigurationManager.AppSettings["ImpersonatorDomain"];
// This is for the user for whom the appointment need to be set on their exchange server. This user will be impersonated by the above impersonator. You do not need to get the password information for this user, just the email address will work.
private string Username ="mtyagi#talygen.local";// HttpContext.Current.User.Identity.Name.Split('\\').Last(); //extract the username out of the "Domain\Username" format. It doesn't have to be the currently logged in user. As per your need you can use the username of any other company user for whom you know the email address.
protected string ImpersonatedEmailAddress;//= Username +"#"+ WebConfigurationManager.AppSettings["EmailDomain"];
//start impersonation setup block. Credits: Impersonate a Specific User in Code http://support.microsoft.com/kb/306158#4
public const int LOGON32_LOGON_INTERACTIVE = 2;
public const int LOGON32_PROVIDER_DEFAULT = 0;
WindowsImpersonationContext impersonationContext;
[DllImport("advapi32.dll")]
public static extern int LogonUserA(String lpszUserName,
String lpszDomain,
String lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int DuplicateToken(IntPtr hToken,
int impersonationLevel,
ref IntPtr hNewToken);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool RevertToSelf();
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern bool CloseHandle(IntPtr handle);
//end impersonation setup block;
protected void Page_Load(object sender, EventArgs e)
{
ImpersonatedEmailAddress = Username;// + "#" + WebConfigurationManager.AppSettings["EmailDomain"]; //form the email address out of the username, provided they both are same
service = new ExchangeService(ExchangeVersion.Exchange2013);
//service.UseDefaultCredentials = true;
service.Credentials = new WebCredentials(ImpersonatorUsername, ImpersonatorPassword, ImpersonatorDomain);
service.Url = new Uri("https://exchange.talygen.com/EWS/exchange.asmx");//new Uri(WebConfigurationManager.AppSettings["EWSURL"]);
service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, ImpersonatedEmailAddress);
SetAppointment("Test", DateTime.Now, "Test");
}
public void SetAppointment(string Subject, DateTime AptDateTime, string Body)
{
Appointment apt = new Appointment(service);
apt.Subject = Subject;
apt.Body = Body;
apt.Body.BodyType = BodyType.HTML;
apt.Start = AptDateTime;
apt.End = apt.Start.AddMinutes(30.00);
apt.ReminderMinutesBeforeStart = 15;
apt.IsReminderSet = true;
if (impersonateValidUser(ImpersonatorUsername, ImpersonatorDomain, ImpersonatorPassword)) //For this code to work you will have to enable impersonation on the Exchange server. This code works on the web application running on the company server, but not from my XP PC that is not part of the domain but is on VPN connection.
{
HttpContext.Current.Trace.Write("Before Saving Appointment. System.Security.Principal.WindowsIdentity.GetCurrent().Name = " + System.Security.Principal.WindowsIdentity.GetCurrent().Name);
apt.Save(SendInvitationsMode.SendToNone);
HttpContext.Current.Trace.Write("After Saving Appointment.");
Label1.Text = String.Format("Appointment set successfully for {0}", ImpersonatedEmailAddress);
}
else //fall back to the code that uses logged in user's window identity and not impersonation. This code "strangely" worked from the web application installed on my Windows XP PC that was not part of the domain but was on VPN connection and yet saved appointments on the company's exchange server. I guess, the VPN connection compensates for all the mumbo-jumbo round about impersonation code in the impersonateValidUser method. Hack, this code worked even I had not configured the impersonation on the exchange server as they tell you to do at this link: http://msdn.microsoft.com/en-us/library/office/bb204095(v=exchg.140).aspx
{
service.Credentials = null;
service.ImpersonatedUserId = null;
service.UseDefaultCredentials = true;
HttpContext.Current.Trace.Write("Before Impersonation: System.Security.Principal.WindowsIdentity.GetCurrent().Name = " + System.Security.Principal.WindowsIdentity.GetCurrent().Name);
//this is not impersonation. It uses the logged in user's window identity. The window identity does not have to be that of the company domain. The windows identity of Local PC that is not part of the domain will also work
System.Security.Principal.WindowsImpersonationContext impersonationContext;
impersonationContext = ((System.Security.Principal.WindowsIdentity)HttpContext.Current.User.Identity).Impersonate();// //System.Threading.Thread.CurrentPrincipal.Identity
HttpContext.Current.Trace.Write("Before Saving Appointment. System.Security.Principal.WindowsIdentity.GetCurrent().Name = " + System.Security.Principal.WindowsIdentity.GetCurrent().Name);
apt.Save(SendInvitationsMode.SendToNone);
impersonationContext.Undo();
}
}
//impersonation methods. Credit: Impersonate a Specific User in Code: http://support.microsoft.com/kb/306158#4
private bool impersonateValidUser(String userName, String domain, String password)
{
WindowsIdentity tempWindowsIdentity;
IntPtr token = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero;
if (RevertToSelf())
{
if (LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT, ref token) != 0)
{
if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
{
tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
impersonationContext = tempWindowsIdentity.Impersonate();
if (impersonationContext != null)
{
CloseHandle(token);
CloseHandle(tokenDuplicate);
return true;
}
}
}
}
if (token != IntPtr.Zero)
CloseHandle(token);
if (tokenDuplicate != IntPtr.Zero)
CloseHandle(tokenDuplicate);
return false;
}
private void undoImpersonation()
{
impersonationContext.Undo();
}
}
}
And my web config code is as bellow:
<?xml version="1.0" encoding="utf-8"?>
<!--
For more information on how to configure your ASP.NET application, please visit
http://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />`enter code here
</configSections>
<connectionStrings>
<add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=aspnet-MvcApplication1-20140210213058;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnet-MvcApplication1-20140210213058.mdf" providerName="System.Data.SqlClient" />
</connectionStrings>
<appSettings>
<add key="webpages:Version" value="2.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="PreserveLoginUrl" value="true" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" />
<!--<authentication mode="Forms">
<forms loginUrl="~/Account/Login" timeout="2880" />
</authentication>-->
<authentication mode="Windows" />
<identity impersonate="true" />
<pages>
<namespaces>
<add namespace="System.Web.Helpers" />
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Optimization" />
<add namespace="System.Web.Routing" />
<add namespace="System.Web.WebPages" />
</namespaces>
</pages>
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<handlers>
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
</entityFramework>
</configuration>
Please help me in short out this problem.
Thanks Mukesh
Your asp.net 4.0 web application needs to run under a service account that has Exchange impersonation rights for the mailbox users. Assuming everyone is in the same Exchange organization, you'll need to run the New-ManagementRoleAssignment cmdlet to grant impersonation privileges for your service account.
Then you'll need to do impersonation just like you have in your example. You won't use Windows impersonation.

WebAPI DELETE request return 404 error in Azure

I have been trying to get the DELETE requests in my ASP.net WebAPI(ASP.net web role) working on Azure and locally on my machine.But end up getting "not found" error.
I have following configuration for the web.config of the ASP.net WebAPI web role:
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules>
<remove name="WebDAVModule" />
</modules>
<handlers>
<remove name="WebDAV" />
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit"
path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS"
modules="IsapiModule"
scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll"
preCondition="classicMode,runtimeVersionv4.0,bitness32"
responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit"
path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS"
modules="IsapiModule"
scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll"
preCondition="classicMode,runtimeVersionv4.0,bitness64"
responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-Integrated-4.0"
path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS"
type="System.Web.Handlers.TransferRequestHandler"
preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
For making it work on IISExpress, I changed the $:\Users\\Documents\IISExpress\config\applicationhost.config configuration and commented out the WebDav portions of it and added the "PUT,DELETE" verbs appropriately.
To test my WebAPI I created a simple windows forms (.net 4.5 ) c# application and used the httpclient as below:
const string key = "user1";
var client = new HttpClient { BaseAddress = new Uri("http://abcd.cloudapp.net/") };
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
var requestUrl = string.Format("api/user/{0}", key);
var deleteAsync = client.DeleteAsync(requestUrl).Result;
The response I get it following:
{StatusCode: 404,
ReasonPhrase: 'Not Found',
Version: 1.1,
Content: System.Net.Http.StreamContent,
Headers:
{
Pragma: no-cache
Cache-Control: no-cache
Date: Fri, 12 Apr 2013 06:40:31 GMT
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Content-Length: 128
Content-Type: application/json; charset=utf-8
Expires: -1
}} System.Net.Http.HttpResponseMessage
How do I get it to work on Azure? and possibly on my local machine as well.

wad-iis-failedreqlogfiles can't be found in my blob

I use this web.config:
<traceAreas>
<add provider="ASP" verbosity="Verbose" />
<add provider="ASPNET" areas="Infrastructure,Module,Page,AppServices" verbosity="Verbose" />
<add provider="ISAPI Extension" verbosity="Verbose" />
<add provider="WWW Server" areas="Security" verbosity="Verbose" />
</traceAreas>
<failureDefinitions statusCodes="200-999" />
And in webrole.cs
public override bool OnStart()
{
//Get Default Config
DiagnosticMonitorConfiguration config = DiagnosticMonitor.GetDefaultInitialConfiguration();
//IIS Logs
config.Directories.ScheduledTransferPeriod = TimeSpan.FromMinutes(1);
Trace.WriteLine("WAD Monitor started", "Information");
DiagnosticMonitor.Start("Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString", config);
RoleEnvironment.Changing += RoleEnvironmentChanging;
return base.OnStart();
}
I can get wad-iis-logsfiles blob, but I can't get wad-iis-failedreqlogfiles blob on my emulator
Why since 200-999 include all request!
And should have a log files.
Well, what I did is to set up my settings in the WebRole file and the code that I added to my web.config are this configurations
<system.diagnostics>
<trace>
<listeners>
<add type="Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener, Microsoft.WindowsAzure.Diagnostics, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
name="AzureDiagnostics">
<filter type="" />
</add>
</listeners>
</trace>
</system.diagnostics>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<tracing>
<traceFailedRequests>
<add path="*">
<traceAreas>
<add provider="ASP" verbosity="Verbose" />
<add provider="ASPNET" areas="Infrastructure,Module,Page,AppServices" verbosity="Verbose" />
<add provider="ISAPI Extension" verbosity="Verbose" />
<add provider="WWW Server" areas="Authentication,Security,Filter,StaticFile,CGI,Compression,Cache,RequestNotifications,Module" verbosity="Verbose" />
</traceAreas>
<failureDefinitions verbosity="Warning" statusCodes="400-599" />
</add>
</traceFailedRequests>
</tracing>
</system.webServer>
And then I implement the method Onstart with this configurations.
public override bool OnStart()
{
String wadConnectionString = "Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString";
CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue(wadConnectionString));
RoleInstanceDiagnosticManager roleInstanceDiagnosticManager = cloudStorageAccount.CreateRoleInstanceDiagnosticManager(
RoleEnvironment.DeploymentId,
RoleEnvironment.CurrentRoleInstance.Role.Name,
RoleEnvironment.CurrentRoleInstance.Id);
DiagnosticMonitorConfiguration config = roleInstanceDiagnosticManager.GetCurrentConfiguration();
//Add Events
config.WindowsEventLog.DataSources.Add("System!*");
config.WindowsEventLog.DataSources.Add("Application!*");
config.WindowsEventLog.ScheduledTransferLogLevelFilter = LogLevel.Error;
config.WindowsEventLog.ScheduledTransferPeriod =TimeSpan.FromSeconds(15.0);
config.Logs.ScheduledTransferLogLevelFilter = LogLevel.Verbose;
config.Logs.ScheduledTransferPeriod = TimeSpan.FromSeconds(15.0);
//transfer the IIS and IIS Failed Request Logs
config.Directories.ScheduledTransferPeriod = TimeSpan.FromMinutes(1.0);
roleInstanceDiagnosticManager.SetCurrentConfiguration(config);
return base.OnStart();
}
And also I recommend you to check your ConnectionString on your WerRole settings, it should look something like this:
"DefaultEndpointsProtocol=http;AccountName=myAccount;AccountKey=8zTMPlQ8N76cEUNGLYhIvPf8lDmmTnCm7BICX/xtPmdr9vN7elOvZS5N2njtg+tbStoCoe30doN0sCrE1LHcsd=="
or
"UseDevelopmentStorage=true"
If you want to work on your development enviroment
Also you can take a look to this site for more details
http://robindotnet.wordpress.com/2011/02/16/azure-toolssdk-1-3-and-iis-logging/
Finally I found the answer!
This is because IIS applicationHost auto disable the trace log file.
When I add this code to webrole.cs and input a invalid url it works!
using (ServerManager serverManager = new ServerManager())
{
Configuration iisConfig = serverManager.GetApplicationHostConfiguration();
ConfigurationSection sitesSection = iisConfig.GetSection("system.applicationHost/sites");
ConfigurationElement siteDefaultsElement = sitesSection.GetChildElement("siteDefaults");
ConfigurationElement logFileElement = siteDefaultsElement.GetChildElement("logFile");
logFileElement["enabled"] = true;
serverManager.CommitChanges();
}

Resources