outputCacheProfiles with Redis cache - azure

I have an MVC web project and I am trying to setup OutputCache for some of the pages using redis cache running locally, eventually to be hosted in azure.
I have decorated my ActionResult with
[OutputCache(CacheProfile = "cacheprofile1")]
and have the following in my web.config under system.web / caching
<outputCacheSettings>
<outputCacheProfiles>
<add name="cacheprofile1" duration="1800" varyByParam="none"/>
</outputCacheProfiles>
</outputCacheSettings>
My Cache provider is set accordingly
<outputCache defaultProvider="localRedisOutputCache">
<providers>
<add name="localRedisOutputCache" type="Microsoft.Web.Redis.RedisOutputCacheProvider" host="127.0.0.1" accessKey="" ssl="false" />
</providers>
</outputCache>
No entries are being made into my cache. If I change my ActionResult decoration to
[OutputCache(Duration=1800)]
it works, but I'd rather not have to set this manually against each method.
Any ideas on why the cache profile is being ignored and how to resolve would be appreciated.

Related

Adding <customHeaders> in webconfig causes 500 error in sub applications in IIS?

My web site is written by ASP.NET MVC 4 and hosted on IIS 6.2.
I need to add custom headers(X-Frame-Options,X-XSS-Protection etc.) to web config in main application.
<httpProtocol>
<customHeaders>
<add name="X-Frame-Options" value="SAMEORIGIN" />
<add name="X-XSS-Protection" value="1" />
<add name="X-Content-Type-Options" value="nosniff" />
</customHeaders>
</httpProtocol>
After I did it, my sub apllications getting http 500 error.I have no idea why this happening.
I already tried option.Also tried remove every customheaders from response headers in IIS, also tried add manually in response headers.
Can you give me an advice to fix this issue?
Try adding the header at the Server level by using "HTTP Response Header" applet.
I think you are adding headers in the "Default Web Site" now. Default Site the header starting with "X-" will give error. I had faced this issue.
You can also try adding it in each App or virtual directory under "Default Web Site".

application Initialization webapi always requesting default.aspx

I've been trying to configure IIS to request a custom URL to warm up my webapi.
My config is like this.
<applicationInitialization doAppInitAfterRestart="true" skipManagedModules="false">
<add initializationPage="/api/transaction/5" />
</applicationInitialization>
This is working but IIS also calls the root web app (/default.aspx) to warm up as well. And I'm wondering how to remove this call as I don't need it.
Thanks for you help!
Patrick
Looks like this config section is working with collection of initialization elements. Try to clear this collection before adding your page:
<applicationInitialization doAppInitAfterRestart="true" skipManagedModules="false">
<clear/>
<add initializationPage="/api/transaction/5" />
</applicationInitialization>

ELMAH - Get SMTP credentials from Azure Application Settings

I've got an Azure Web App using ELMAH to log unhandled exceptions.
When I first deployed it, the web.config had the full SMTP setup defined in it, and ELMAH emailed exceptions:
<system.net>
<mailSettings>
<smtp from="me#mydomain.com">
<network host="smtp.mailprovider.com"
port="123"
userName="myUserName"
password="p#ssw0rd" />
</stmp>
</mailSettings>
</system.net>
The username and password have since been removed from the web.config, and they're now stored as application settings, configured through the Azure Portal.
Most of the emails I send still work fine, as the email code can access these application settings and use them when instantiating the SmtpClient, e.g.:
var userName = WebConfigurationManager.AppSettings["smtp.userName"];
var password = WebConfigurationManager.AppSettings["smtp.password"];
var credentials = new NetworkCredential(userName, password);
using (var smtpClient = new SmtpClient { Credentials = credentials })
{
await smtpClient.SendMailAsync(mailMessage);
}
What's the best way to get ELMAH to use the credentials stored in the application settings?
Options I can see:
There is a page on the wiki explaining how to use ELMAH's ErrorTweetModule to do an HTTP form post with the error details to any URL. The controller receiving the post could then use the stored credentials to email the details on.
The WebBase has a link to an article suggesting you can send emails directly to the recipient's SMTP server without authentication, but it says this may not work if you have DomainKeys set up, which I do.
This answer links to an article about intercepting the Mailing event, to customise the message.
I ended up creating a custom version of Elmah's ErrorMailModule, derived from the standard one, but overriding the SendMail method, based on some advice from Atif Aziz in a discussion on Google Groups.
The only changes required were to create the new module, and switch the Web.Config to use the custom module instead of the standard one.
Module
using System;
using System.Net.Mail;
namespace Test
{
public class ErrorMailModule : Elmah.ErrorMailModule
{
protected override void SendMail(MailMessage mail)
{
if (mail == null) throw new ArgumentNullException(nameof(mail));
// do what you want with the mail
// (in my case this fires up the email service, which
// gets the credentials from the Azure settings)
}
}
}
Web Config Changes
All that's required is to change the two occurrences of Elmah.ErrorLogModule, Elmah to your own module, in this case Test.ErrorMailModule.
So, instead of this...
<system.web>
<httpModules>
<add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" />
</httpModules>
</system.web>
<system.webServer>
<modules>
<add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" preCondition="managedHandler" />
</modules>
</system.webServer>
...you should now have this:
<system.web>
<httpModules>
<add name="ErrorMail" type="Test.ErrorMailModule" />
</httpModules>
</system.web>
<system.webServer>
<modules>
<add name="ErrorMail" type="Test.ErrorMailModule" preCondition="managedHandler" />
</modules>
</system.webServer>
You will still need the errorMail section, as Elmah is still responsible for creating the email. Mine looks like this:
<elmah>
<errorMail from="user#domain.com" to="user#domain.com" subject="Custom Email Module"/>
</elmah>
Creating a HTTP request could work, but that should be the solution if everything else doesn't work IMO. Intercepting the Mailing event doesn't work, since you do not have access to the SmtpClient with the credentials in that event.
I've looked at different ways to update the SMTP settings from code. At first I though that I could just get a reference to the smtp section and update the properties, since they all have setter. But the code throw a configuration exception on runtime.
From what I can find, the only way to update the username and password in smtp section, is to read the web.config, update it and write the new version. Here's an example of writing updates to web.config:
var configuration = WebConfigurationManager.OpenWebConfiguration("~");
var section = configuration.GetSection("system.net/mailSettings/smtp") as SmtpSection;
section.Network.UserName = ConfigurationManager.AppSettings["myusername"];
section.Network.Password = ConfigurationManager.AppSettings["mypassword"];
configuration.Save();
The code actually updates the web.config. The code can be run at startup, but that would modify your web.config file locally as well. Another approach would be to run the code as part of a post deployment task with Azure.

Microsoft.Owin.StaticFiles works in console host but I get a 404 in IIS on file requests

I have Microsoft.Owin.FileServer (v2.1.0) set up in my Owin pipeline, and setting up FileServerOptions with EnableDirectoryBrowsing = true works great for showing the directory contents in both my console host and iisexpress.
It's when I try to view a particular file (so, the StaticFiles part) I have problems in iisexpress. Still works great in the console host, but in iisexpress I get a 404:
HTTP Error 404.0 - Not Found
The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.
Most likely causes:
- The directory or file specified does not exist on the Web server.
- The URL contains a typographical error.
- A custom filter or module, such as URLScan, restricts access to the file.
I do have the latest Microsoft.Owin.Host.SystemWeb referenced in the web host.
Adding <modules runAllManagedModulesForAllRequests="true"> didn't work for me (VS2013, IIS Express).
Forcing all requests to use the Owin pipeline did:
(in web.config)
<configuration>
<system.webServer>
<handlers>
<add name="Owin" verb="" path="*" type="Microsoft.Owin.Host.SystemWeb.OwinHttpHandler, Microsoft.Owin.Host.SystemWeb"/>
</handlers>
</system.webServer>
</configuration>
I had to add the following setting:
<modules runAllManagedModulesForAllRequests="true">
to get the module that Microsoft.Owin.Host.SystemWeb automatically registers to run for routes like *.txt, *.js that IIS was assuming were static files to run through the Owin pipeline.
This setting does have performance implications for actual static files, but this works for me.
I've just struggled with this for the last couple of hours, adding the handler below did work however I don't believe this was the correct approach, it caused public void Configuration(IAppBuilder appBuilder) to be invoked twice.
<add name="Owin" verb="" path="*" type="Microsoft.Owin.Host.SystemWeb.OwinHttpHandler, Microsoft.Owin.Host.SystemWeb"/>
I did some reading and found https://learn.microsoft.com/en-us/aspnet/aspnet/overview/owin-and-katana/owin-middleware-in-the-iis-integrated-pipeline
which then lead me to use UseStageMarked().
So now my call to UseStaticFiles() is followed by a called to UseStageMarker() like so:
appBuilder.UseStaticFiles();
//allows owin middlwares to be executed earlier on in the pipeline.
appBuilder.UseStageMarker(PipelineStage.Authenticate);
There is a very good read on it here:
You can find UseStageMarker inside the Microsoft.Owin package here: https://www.nuget.org/packages/Microsoft.Owin/
I hope this helps someone else.
Thanks
Steve

azure cache preview

I tried the new azure preview that came with the new sdk on my computer.
I put a worker role with cache preview and put co-located role with 30% cache size.
on my controller i put this code:
[OutputCache(Duration=int.MaxValue, VaryByParam="none")]
public ActionResult Index()
{
ViewBag.Message = "Welcome to ASP.NET MVC!";
ViewBag.Id = Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.CurrentRoleInstance.Id;
return View();
}
now i ran the worker role via the emulator with 4 instances. the result was that every time i saw a different id - which mean the output cache never work with all the 4 instances ( to be clear i configure the output cache to work with the cache preview).
Only when i put an extra cache worker role as dedicated role everything start to work like it should be.
My questions is:
Do i need the extra worker role to actually make the cache preview to work ok? - which mean the trade off of not working with azure appfabric cache is putting extra machine
Did i do something work and it should work with the web roles as co located roles?
thanks
edit:
this another section of my web.config
<dataCacheClients>
<tracing sinkType="DiagnosticSink" traceLevel="Error" />
<dataCacheClient name="default">
<autoDiscover isEnabled="true" identifier="NugetTest" />
<!--<localCache isEnabled="true" sync="TimeoutBased" objectCount="100000" ttlValue="300" />
</dataCacheClient>
if my identifier have NugetTest ( which is my web roles - which i have 4) every time i switch machine i get a different cache. if i change the identifier to my worker role i get the result
Can you add applicationName tag in the provider configuration in web.config of you app? If this is not added, instances will not share the cache across. Please note the applicationName tag.
This should be added for the web.config of webrole in both dedicated or colocated cache scenario.
Please reply if this solves your issue.
<caching>
<outputCache defaultProvider="DistributedCache">
<providers>
<add name="DistributedCache" type="Microsoft.Web.DistributedCache.DistributedCacheOutputCacheProvider, Microsoft.Web.DistributedCache" cacheName="<cacheName>" applicationName ="<anyName>" dataCacheClientName="<dataCacheClientName>" />
</providers>
</outputCache>
</caching>
I'm unable to reproduce this issue. I always see the same instance, and I'm using Ctrl+F5 in the browser (thus rule out browser cache). PLease make sure you've configured output cache provider as described on http://www.windowsazure.com/en-us/develop/net/how-to-guides/cache/.
<!-- If output cache content needs to be saved in a Windows Azure
cache, add the following to web.config inside system.web. -->
<caching>
<outputCache defaultProvider="DistributedCache">
<providers>
<add name="DistributedCache"
type="Microsoft.Web.DistributedCache.DistributedCacheOutputCacheProvider, Microsoft.Web.DistributedCache"
cacheName="default"
dataCacheClientName="default" />
</providers>
</outputCache>
</caching>
Best Regards,
Ming Xu.

Resources