File download from azure services hosted application get stuck for IE 11 - asp.net-mvc

We noticed that file download get stuck after some time in IE 11 client browser if downloaded from ASP.NET MVC application deployed to Azure service. The file download starts normally in IE 11. For several minutes the downloaded file size get increased. Then the yet downloaded file size get stuck with no more increases. If we continue to wait even more for around 1h, then the IE shows 'download was interrupted' error.
Azure instances have IIS 8.5 on board with app pool in default integrated pipeline mode. Application is ASP.NET MVC 5, targeted .NET 4.5.2.
There are no problems with download from Azure for Chrome browser.
There are no problems with download from local IIS express for both IE 11 and Chrome browsers.
There are no problems with download from local IIS 7.5 for both IE 11 and Chrome browsers.
So it looks like the only problem pair is Azure hosted IIS 8.5 + IE 11.
Application use the following code to stream file to client:
private const int StreamBufferSize = 1024*128; // 128KB
public static async Task StreamData(string fileName, Func<Stream, Task> streamFiller, HttpResponseBase response)
{
response.AddHeader("Content-Disposition", string.Format("attachment;filename=\"{0}\"", fileName));
response.ContentType = MimeMapping.GetMimeMapping(fileName);
response.BufferOutput = false;
using (Stream outputStream = new BufferedStream(response.OutputStream, StreamBufferSize))
{
await streamFiller(outputStream);
}
}
Where 'streamFiller()' is externally passed Func that writes data to the stream.
Please note that file is not so large, around 20Mb, but server do not send it at once. Instead server streams file with buffered chunks (see code above). Time between each chunk get streamed (buffer flashed) may be as long as several minutes.
By looking into Azure IIS I found that the client request looks like the following:
during normal download phase: State: ExecureRequestHandler, Module Name: ManagedPipelineHandler
since the download get stuck: State: SendResponse, Module Name: RemoveUnnecessaryHeadersModule.
To be clear what is RemoveUnnecessaryHeadersModule: we do the 'Server' header removing as following:
public class RemoveUnnecessaryHeadersModule : IHttpModule
{
public void Init(HttpApplication context)
{
// This only works if running in IIS7+ Integrated Pipeline mode
if (!HttpRuntime.UsingIntegratedPipeline) return;
context.PreSendRequestHeaders += (sender, e) =>
{
var app = sender as HttpApplication;
if (app != null && app.Context != null)
{
app.Context.Response.Headers.Remove("Server");
}
};
}
}

Related

I am getting 404 not found for download a PDF on my Azure app but works locally

I am currently running ASPNET Core MVC app on an Azure server (.net core 3.1), and I am getting 404 when trying to download a PDF file. This works perfectly fine locally but gets 404 when I publish to Azure.
I have no problems downloading a CSV file (whether locally or Azure).
// Works locally and in Azure
public async Task<IActionResult> DownloadCSV()
{
var report = await _basicCsvGameReportService.CreateReportAsync();
return File(report, "text/csv", "relatorio.csv");
}
// Works locally only
public async Task<IActionResult> DownloadPDF()
{
var report = await _basicPdfGameReportService.CreateReportAsync();
return File(report, "application/pdf", "relatorio.pdf");
}

Azure RoleEnvironment.Changing event not being called in ASP.NET MVC 5

I am trying to use the Azure Runtime Reconfiguration Pattern to allow me to change a appSetting in the normal Web.config file via PowerShell (later by Microsoft Azure Web Sites Management Library).
My problem is that the RoleEnvironment.Changing event is not being called in my MVC app, so the web app is being restarted. I have placed event set up code in the MVC Application_Start as described in the Azure article, i.e.
protected void Application_Start()
{
RoleEnvironment.Changing += RoleEnvironment_Changing;
RoleEnvironment.Changed += RoleEnvironment_Changed;
//normal MVC code etc...
AreaRegistration.RegisterAllAreas();
}
The event handlers are a straight copy of the handled from the Azure article and look like this:
private const string CustomSettingName = "TestConfig";
public static string TestConfigValue;
private static void RoleEnvironment_Changing(object sender,
RoleEnvironmentChangingEventArgs e)
{
RoleLogs.Add("RoleEnvironment_Changing: started");
var changedSettings = e.Changes.OfType<RoleEnvironmentConfigurationSettingChange>()
.Select(c => c.ConfigurationSettingName).ToList();
Trace.TraceInformation("Changing notification. Settings being changed: "
+ string.Join(", ", changedSettings));
if (changedSettings
.Any(settingName => !string.Equals(settingName, CustomSettingName,
StringComparison.Ordinal)))
{
Console.WriteLine("Cancelling dynamic configuration change (restarting).");
RoleLogs.Add("RoleEnvironment_Changing: restarting!");
// Setting this to true will restart the role gracefully. If Cancel is not
// set to true, and the change is not handled by the application, the
// application will not use the new value until it is restarted (either
// manually or for some other reason).
e.Cancel = true;
}
else
{
RoleLogs.Add("RoleEnvironment_Changing: change is OK. Not restarting");
Console.WriteLine("Handling configuration change without restarting. ");
}
}
private static void RoleEnvironment_Changed(object sender,
RoleEnvironmentChangedEventArgs e)
{
RoleLogs.Add("RoleEnvironment_ChangED: Starting");
Console.WriteLine("Updating instance with new configuration settings.");
foreach (var settingChange in
e.Changes.OfType<RoleEnvironmentConfigurationSettingChange>())
{
if (string.Equals(settingChange.ConfigurationSettingName,
CustomSettingName,
StringComparison.Ordinal))
{
// Execute a function to update the configuration of the component.
RoleLogs.Add("RoleEnvironment_ChangED: TestConfig has changed");
Console.WriteLine("TestConfig has changed.");
TestConfigValue = RoleEnvironment.GetConfigurationSettingValue(CustomSettingName);
}
}
}
I have added logs which prove that my RoleEnvironment_Changing and RoleEnvironment_Changed are not being called in the MVC WebApp which means the WebApp is restarted when I change an appSetting via PowerShell. This also means the RoleEnvironment.Changing event never gets to the WebJob.
I am using Azure SDK 2.7.0
Any ideas?
UPDATE
#richag gave me an answer, which made me realise that my problem is because I am using a App Service rather than a Cloud Service. This SO answer and plus this video (see at 5:00mins) talks about the difference (Note: the video is old so the name of the web app is different, but the concept is the same).
I don't really want to change this late in the development, and I have worked round the problem another way. Maybe on the next project and will look at Cloud Services as I can see some positives, like better control of my WebJobs configuration.
From the runtime reconfiguration pattern: "Microsoft Azure Cloud Services roles detect and expose two events that are raised when the hosting environment detects a change to the ServiceConfiguration.cscfg files" These events are not fired if you make changes to app.config/web.config files. Only when the cloud service configuration is changed, i.e. if you upload a new configuration file through the azure portal's configure tab or change a setting directly on the azure portal.
According to the debugger, none of the following events are fired when I update the Azure Portal to change an AppSetting for an ASP.NET WebAPI app:
RoleEnvironment.Changing
RoleEnvironment.Changed
RoleEnvironment.StatusCheck
RoleEnvironment.SimultaneousChanging
RoleEnvironment.SimultaneousChanged
RoleEnvironment.Stopping
Do others have different experience?

Get Error (error=access_denied) while logging in MVC5 application with facebook SDK

I have developed an application with ASP.NET MVC5. I have used Facebook external authentication in my application.
When I debug this application with the "Locallhost" domain, the Facebook login works well but when I publish the application in the main server,the AuthenticationManager.GetExternalLoginInfo() returns null and it gives me an error like this in the url:
http://xxxxx.com/Account/ExternalLoginCallback?ReturnUrl=%2Fen&error=access_denied#_=_
I have set the "Site URL" as "http://xxxx.com" and "Valid OAuth redirect URIs" as "http://xxxx.com/signin-facebook" in the Facebook development console.
My setting in the Startup.Outh.cs file is:
var FacebookOptions = new Microsoft.Owin.Security.Facebook.FacebookAuthenticationOptions();
FacebookOptions.AppId = ConfigurationManager.AppSettings["Facebook_User_Key"];
FacebookOptions.AppSecret = ConfigurationManager.AppSettings["Facebook_Secret_Key"];
FacebookOptions.Provider = new Microsoft.Owin.Security.Facebook.FacebookAuthenticationProvider()
{
OnAuthenticated = async context =>
{
context.Identity.AddClaim(new System.Security.Claims.Claim("FacebookAccessToken", context.AccessToken));
foreach (var claim in context.User)
{
var claimType = string.Format("urn:facebook:{0}", claim.Key);
string claimValue = claim.Value.ToString();
if (!context.Identity.HasClaim(claimType, claimValue))
context.Identity.AddClaim(new System.Security.Claims.Claim(claimType, claimValue, "XmlSchemaString", "Facebook"));
}
}
};
FacebookOptions.SignInAsAuthenticationType = DefaultAuthenticationTypes.ExternalCookie;
app.UseFacebookAuthentication(FacebookOptions);
I don't know why the external login does not work only in the server with my main domain name. please help me about this problem.
I encountered pretty much the same symptoms you describe:
shortly:
A Facebook authentication worked well on localhost, and after uploading the project to another server (and changing the site URL on Facebook console), authentication did not succeed.
I would recommend you roll back to the MVC template code, and if that works - notice any changes you have made to the middleware code (Startup.Auth.sc).
In particular pay attention to code that interacts with LOCAL configuration, such as Disk I/O and OS permissions for local services.
My particular case:
Starting from the Owin/Katana supported Visual Studio template of a WebAPI project, external login was working perfectly with Facebook, Microsoft and Google OAuth middleware, when testing on localhost.
Later I added come code to Startup.Auth.sc because I needed further authentication activity.
So this was the original code:
public void ConfigureAuth(IAppBuilder app)
{
// see WebAPI template of Visual Studio 2013/2015
...
app.UseFacebookAuthentication(
appId: 99999999,
appSecret: *******);
}
and this was replacement:
public void ConfigureAuth(IAppBuilder app)
{
// see WebAPI template of Visual Studio 2013/2015
...
app.UseFacebookAuthentication(GetFacebookAuth());
}
private FacebookAuthenticationOptions GetFacebookAuth()
{
string picRequest =
String.Format("/me/picture?redirect=false&width={0}&height={0}", ProfileInfoClaimsModel.PIC_SIDE_PX);
var facebookProvider = new FacebookAuthenticationProvider()
{
OnAuthenticated = async (context) =>
{
var client = new FacebookClient(context.AccessToken);
dynamic me = client.Get("/me?fields=id,name,locale");
dynamic mePicture = client.Get(picRequest);
// storing temporary social profile info TO A LOCAL FOLDER
// uploading the local folder to a service WITH A LOCAL CREDENTIAL FILE
...
}
};
var options = new FacebookAuthenticationOptions()
{
AppId = 0123456789,
AppSecret = ******,
Provider = facebookProvider,
};
return options;
}
You may notice that my comments will make the problem obvious - the code points to local resources.
Then I published the project to a virtual server (by Amazon EC2) running Windows Server 2012 with IIS 8.5.
From that moment I kept getting error=access_denied in the redirect from /signin-facebook.
I decided to follow this good old concept, and go back to the original template code. Pretty soon I figured out that I forgot to configure the new server. For instance, the folder the code refers to did not exist and the site had no permission to create it.
Obviously, that solved it.

How to print from MVC3 controller from server

Code below is used to print from ASP .NET MVC3 application to Samsung ML-331x Series printer connected to IP address in LAN and shared in server as Samsung ML-331x Series
Nothing is printed. Execution stops at doc.Print() line.
Every controller call adds new unfinished job:
Those jobs are never finished, only iisreset clears them.
Server is Windows 2003 + IIS
It worked in MVC2 .NET 3.5 application. ForteSSL VPN was installed in server and application was upgraded to
MVC3 and .NET 4.
(After that printing was not checked immediately, so I'm not sure is this related to those changes).
User NETWORK SERVICE with all permissions is added to printer users but problem persists.
Running application in development computer by pressing F5 in visual studio with Web Developer server and calling with controller to print to PDF Creator works OK.
How to print from controller in server ?
public ActionResult PrintTest()
{
var doc = new PrintDocument();
doc.PrinterSettings.PrinterName = "Samsung ML-331x Series";
doc.PrintPage += new PrintPageEventHandler(TestProvideContent);
doc.Print();
return new ContentResult()
{
Content = "Printed"
};
}
public void TestProvideContent(object sender, PrintPageEventArgs e)
{
e.Graphics.DrawString("Test",
new Font("Arial", 12),
Brushes.Black,
e.MarginBounds.Left,
e.MarginBounds.Top);
}
Update
Application runs at full trust Level.
Application log in event viewer does not have any entries about this.
Using Programmatically "hello world" default SERVER-side printer in ASP.NET MVC I tried to use printer name with server name as \\SERVER\Samsung ML-331x Series but problem persists.

running express.js app in Asp.net MVC

I would like to run node.js with asp.net mvc for performing socket.io operations.
i've successfully included the node.js in asp.net mvc as described in here
my problem is how to run express.js in asp.net mvc,
i've performed the url rewritting in Global.asax.cs file like
void Application_BeginRequest(object sender, EventArgs e)
{
// Get current path
string CurrentPath = Request.Path.ToLower();
if (CurrentPath.StartsWith("/node"))
{ HttpContext MyContext = HttpContext.Current;
MyContext.RewritePath("/Node/index.js/");
}
}
so in the url http:localhost:1234/node should redirect me to the index.js file in Node folder
it is all working well but,
when i start coading express.js server in index.js like
var express = require('express');
var app = express.createServer();
app.get('/node/', function (req, res) {
res.send(' welcome to express ');
});
app.listen(process.env.PORT);
I got error saying Cannot GET /Node/index.js/
where am i missing? please guide me how to write express.js coading in asp.net mvc
Iam running this application in windows 7 32 bit system with IIS 8.0 express , and installed node versions are
iisnode.js - iisnode-full-iis7-v0.2.3-x86
node.js - node-v0.8.19-x86
Thank you.
Do you have a web.config entry for iisnode handling index.js?
iisnode is not set up as a .js handler by default, since there is far more client-side javascript than server-side javascript, so you need to explicitly turn on iisnode as a handler for that file.

Resources