I have the following code in my Global.asax:
void Application_EndRequest(object sender, EventArgs e)
{
HttpApplication application = sender as HttpApplication;
HttpContext context = application.Context;
string path = context.Request.Path;
string contentType = context.Response.ContentType;
System.Diagnostics.Debug.WriteLine("-----------------------------------");
System.Diagnostics.Debug.WriteLine("Path: " + path);
System.Diagnostics.Debug.WriteLine("ContentType:" + contentType);
}
I have a Help folder at the root of the site (~/Help) that contains static .htm files. I notice that not all of these files are being run through EndRequest. Sometimes I see assets in the page being logged (e.g. .js files) but not the htm file itself. Sometimes they do get logged.
Why don't all of these files run through EndRequest and how can I ensure that they do?
In the end my configuration is like this:
AppPool pipeline: Integrated
RouteExistingFiles: false (default)
runAllManagedModulesForAllRequests: true
All of this was how it was when I wrote up this question. The thing I did different was to go into my web.config and manually add a handler under <httpHandlers>:
<add verb="GET,HEAD,POST,DEBUG" path="*.htm" type="System.Web.UI.PageHandlerFactory" />
One thing that was throwing me off was that once the file had come down the browser was caching it and not re-requesting it (until I cleared the cache).
Related
My ASPNET Zero alway reload all css and js files instead of using cache. That is the reason it was too slow. So how can I change this setting value?
You can add asp-append-version="true" to the script or link tags in the razor pages where your css/js files are included.
Abp does provide dynamic scripts which are created at runtime creation. As such, there are limitations to what you can cache as discussed at https://github.com/aspnetboilerplate/aspnetboilerplate/issues/3673
I have found the reason, the ASPNET Zero disable Client cache by default. My solution is just commented a line of code as below
protected override void Application_BeginRequest(object sender, EventArgs e)
{
base.Application_BeginRequest(sender, e);
//DisableClientCache();
}
private void DisableClientCache()
{
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Cache.SetExpires(CacheExpireDate);
Response.Cache.SetNoStore();
}
I have HttpModule in place for URL encryption; I noticed this module is also intercepting MVC bundle requests; even if I am using following settings:
<modules runAllManagedModulesForAllRequests="false">
<add ..preCondition="managedHandler" />
</modules>
Is there any way to bypass the interception of MVC bundle requests from HttpModule?
so for ignoring certain route in httpmodule you can use Application_BeginRequest or Application_EndRequest , do as below in example which ignores aspx pages or check for the path you want to ignore
Example :
private void Application_BeginRequest(Object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
string filePath = context.Request.FilePath;
string fileExtension = VirtualPathUtility.GetExtension(filePath);
if (fileExtension.Equals(".aspx"))
{
return;
}
}
But if your functionality is related to some modules of application I suggest make use of Filters(MVC sepcific and for modules) rather than HttpModules(Specific to full application).
I have successfully set up using the viewer with the following code:
protected void btnShowPDFS_OnClick(object sender, EventArgs e)
{
// Display all files.
string[] files = Directory.GetFiles(#"D:\Reports\2014\July\", "*.PDF");
var pdfNames = new List<string>();
foreach (string file in files)
{
string fileName = Path.GetFileName(file);
string queryString = "/web/viewer.html?file=" + System.Web.HttpUtility.UrlEncode("../July/" + fileName);
pdfNames.Add(queryString);
}
listView.DataSource = pdfNames;
listView.DataBind();
}
Now, this all works fine if all my PDF's are in a folder within the website (i.e localhost). However, how do i point the view to either a network share, or just another folder on the same machine, but outside of IIS?
A browser's XMLHttpRequest might have a restrictions for local files access (Firefox has more relaxed policy for local file than other browsers).
PDF.js is using XHR; and PDF.js also allows "load" files from a typed array (Uint8Array). You can use the latter in your solution. Notice the Internet Explorer (WebBrowser control) has window.external that can be used to transmit the data from the host application, see http://msdn.microsoft.com/en-us/library/system.windows.forms.webbrowser.objectforscripting(v=vs.110).aspx
In my project we change one image depending on domain which was requested. Of course we can serve different files (css, js, html), but much more easy is to handle this one file and serve user correct one (let's call it logo.ico)
In web.config we set <modules runAllManagedModulesForAllRequests="false"> which causes that that IIS serve all static files for us.
Is there a way to add exception for `logo.ico' file?
To make example clear: when browser request http://mydomian.com/logo.ico I would like to run custom handler. For every other file I would like to use IIS native solution (which means <modules runAllManagedModulesForAllRequests="false">)
There is no way to add exception just for one file, but you could serve that image with ashx handler, for example url should look like (add your own logic to select image)
http://mydomian.com/ServeImage.ashx?image=logo.ico
And then just serve icon for that domain:
public class ServeImage : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "image/x-icon";
using (var fs = new FileStream(context.Server.MapPath("~/App_Data/logo.ico"), FileMode.Open))
{
fs.CopyTo(context.Response.OutputStream);
}
}
public bool IsReusable
{
get
{
return false;
}
}
}
What I'm doing:
I am creating an email mailing engine that takes html templates, replaces tokens with data and then sends off the mail to an SMTP server. Eventually we'll want a CMS UI on top of this to allow them to add/remove file templates or update the content in them via a CMS UI. Anyway I am putting the .htm files for the email templates inside my MVC web project and need to read their contents and get the string of HTML back to work with. If I move all this code out of my MVC project into like a utility C# project layer, the problem is then I have to worry about maintaining physical paths ("C:...\theMVCWebSiteFolder...\Email\Templates\SomeTemplate.htm") and that to me would have to be hard coded I think to keep track if you were to move the site to a different server, different hard drive partition, etc. So I'd like to be able to work with the files using the current application's context unless there's a way to do this agnostic to my MVC app and still not have to worry about having to ever change the location of the physical root every time we move folders.
I've got the following utility method I created in a utility class that sits in a folder somewhere in my ASP.NET MVC web project in just a folder (a folder outside of any view folders:
public static string GetFileData(string filePath)
{
if (!File.Exists(HttpContext.Current.Request.PhysicalApplicationPath + filePath))
throw new FileNotFoundException(String.Format("the file {0} was not found", filePath));
string text;
FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.None);
using(StreamReader read = new StreamReader(fileStream))
text = read.ReadToEnd();
return text;
}
I'm trying to figure out why the context is turning up null here. I originally tried HttpContext.Current but current is coming up null so it can't find the current context in my Utility.cs method that sits in my MVC web project.
UPDATE:
Ok so the consensus is to use HttpRequestBase object and not the HttpContext.Current object. I still find it weird that the HttpContext.Current is null. But moving on, if my Utility.cs is outside any context of a controller or view, then how the heck do I get an instance of the current request (HttpRequestBase) to work with and send an instance that implements HttpRequestBase (I do not know what object that would be if I want to do this in the "MVC way" outside a controller or view) to this utility method?
No idea why this returns null but since it is a bad idea to tie your business layers with ASP.NET specifics I'd recommend you the following change to your method:
public static string GetFileData(string filePath)
{
if (!File.Exists(filePath))
throw new FileNotFoundException(String.Format("the file {0} was not found", filePath));
return File.ReadAllText(filePath);
}
and then when you need to consume it from a web application:
public ActionResult Foo()
{
var result = MyClass.GetFileData(Server.MapPath("~/foo/bar.txt"));
...
}
and when you need to consume it in a WinForms application:
protected void Button1_Click(object sender, EventArgs e)
{
var filePath = Path.Combine(Environment.CurrentDirectory, "bar.txt");
var result = MyClass.GetFileData(filePath);
...
}
In a utility class I would remove the dependency on any web-related stuff.
For a path relative to the application root I would use:
Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, fileName)
which will give you what you probably want (a path relative to the web root directory in a web application; relative to the path containing the executable in a WinForms app, ...)
If want to rewrite that method in asp.net mvc way, you could rewrite it this way and remove coupling with HttpContext class
public static string GetFileData(HttpRequestBase request, string filePath)
{
if (!File.Exists(request.PhysicalApplicationPath + filePath))
throw new FileNotFoundException(String.Format("the file {0} was not found", filePath));
string text;
FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.None);
using(StreamReader read = new StreamReader(fileStream))
text = read.ReadToEnd();
return text;
}
And generally in MVC HttpContext, HttpRequest and HttpResponse are abstracted into HttpContextBase, HttpRequestBase and HttpResponseBase accordingly