Configure an OWIN static file server at a specific route prefix - asp.net

I'm experimenting with keeping my content in non-default locations (eg in bower_components or /packages/../tools). As part of the experiment I am trying to set up an asp.net mvc 5 application where hitting a certain route allows me to browse files in the undersorejs package directory.
I have the following nuget packages (in addition to the default)
Install-Package underscore.js
Install-Package Microsoft.Owin.StaticFiles
Install-Package Microsoft.Owin.Host.SystemWeb
This is what I have in an OWIN startup class
var fileSystem = new PhysicalFileSystem(
HttpContext.Current.Server.MapPath("~")+"/../packages/underscore.js.1.6.0"
);
var options = new FileServerOptions {EnableDirectoryBrowsing = true, FileSystem = fileSystem};
app.MapWhen(ctx =>
ctx.Request.Uri.AbsolutePath.StartsWith("/__underscore"),
ab => ab.UseFileServer(options)
);
To my understanding and previous experimentation this is pretty straightforward - when the request begins with /__underscore use the simple static file server. However when I head over to /__underscore I get a 404 error.
However, placing breakpoints I can see that the UseFileServer lambda executes once on startup and then never again, while the predicate lambda is called on every request (and returns the correct value).
What am I missing?

You need to specify the RequestPath as well:
var options = new FileServerOptions {
EnableDirectoryBrowsing = true,
FileSystem = fileSystem,
RequestPath = PathString.FromUriComponent("/__underscore")
};
As per your comment:
If you're unable to download files, try to explicitly register OwinHttpHandler in your Web.Config:
<system.webServer>
<handlers>
<add name="Owin" verb="" path="*" type="Microsoft.Owin.Host.SystemWeb.OwinHttpHandler, Microsoft.Owin.Host.SystemWeb"/>
</handlers>
</system.webServer>
Alternatively, you can set runAllManagedModulesForAllRequests to 'true':
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<remove name="FormsAuthenticationModule" />
</modules>
</system.webServer>

Related

ASP.NET MVC CORS issue

I have an ASP.NET MVC application (.NET 4.6) where on one occasion I need to redirect to a different domain.
So the code is like this (only authenticated users can come to the controller):
public ActionResult UploadForDesign(int parcelId)
{
......
string url = "differentdomain/parcelId" ;
return ReDirect(url);
}
I am getting an error:
has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin'.....
Failed to load resource: net::ERR_FAILED
I did the following in the control before redirect call
HttpContext.Response.AddHeader("Access-Control-Allow-Origin", "*");
and I still get the same error.
Also I tried the following in web.config, but didn't help much.
<httpProtocol>
<customHeaders>
<clear />
<add name="Access-Control-Allow-Origin" value="*" />
</customHeaders>
</httpProtocol>
Now I had another test bare ASP.NET MVC app (.NET 4.5.2) with no authentication, and the above code works fine. I checked all the code and it looks the same except authentication in place and the framework version.
Any idea what to do?
You can try to use the WithOrigins method on your CORS policy and add whatever domain you need:
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder =>
.WithOrigins("http://localhost:4200/")
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials()
);
});
Ahhh sorry. I believe you should be able to use something like:
var p = new CorsPolicy();
p.AllowAnyHeader = true;
p.AllowAnyMethod = true;
p.AllowAnyOrigin = false;
p.Origins.Add("http://localhost:4200/");

Acces-Control-Allow-Origin works with Web.config (IIS7) but not with (WebApiConfig.cs) ASP.NET Cross Origin support

For a project i want to load and view a pdf file with angular-pdfjs. The team uses ASP.net Cross Origin, to Allow-Acces-Control, Headers, Credentials etc.
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Replace the default implementation of the ITraceWriter with our custom logger.
config.Services.Replace(typeof (ITraceWriter), new GlobalTraceLogger());
// Replace the default exception logger to be able to log exceptions with NLog
config.Services.Replace(typeof (IExceptionLogger), new GlobalExceptionLogger());
// Replace the default exceptionhandler to be able to handle exceptions globally
config.Services.Replace(typeof (IExceptionHandler), new GlobalExceptionHandler());
// We must enable cors, because otherwise we are not able to commuincate with a java script client
// TODO: We need to restirct the requested resource. Do not allow every origin!
// Do not run this in prodocutive environment
var cors = new EnableCorsAttribute("*", "*", "*", "*");
cors.SupportsCredentials = true;
config.EnableCors(cors);
config.MapHttpAttributeRoutes();
// Make the default return type JSON
var appXmlType =
config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml");
config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);
This works good so far, but if i want to load my pdf file with angular-pdfjs, i get a Cross Origin Error, because Allow-Acces-Control-Origin "*" didn't works for my pdf-url.
(https://img3.picload.org/image/roirrgcw/corsworksnot.png)
But if i using instead of ASP.net Cross Origin Support the Allow-Access-Control of IIS7 in Web.config:
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Origin, X-Requested- With, Content-Type, Accept" />
<add name="Access-Control-Allow-Methods" value="GET,POST,PUT,DELETE,OPTIONS" />
<add name="Access-Control-Allow-Credentials" value="true" />
</customHeaders>
</httpProtocol>
it works and the pdf will be loaded correctly.
(https://picload.org/image/roirrgci/corsworks.jpg)
But the problem is, at the moment the page is loaded via "file://" and so i get
an error because there is no Access-Control-Allow-Origin for 'null'. That means, my pdf is loading correctly this way, but the login, pictures... won't be loaded anymore. So my question is, if someone knows how i can change the WebApiConfig-Implementation that my pdf-file get an Access-Controll-Allow as well. Or maybe can someone tell where the error could be.
For information:
Thats the way i'm loading the pdf with angular-pdfjs:
<!---------------------------THE PDF VIEWER DIRECTIVE------------------------->
<div pdf-viewer="options" pdf-url="pdfUrl" id="my-viewer" class="col col-lg-10"></div>
<!---------------------------THE PDF VIEWER DIRECTIVE------------------------->
and thats the url, i'm using:
function PdfviewController(ebmGuideLineService, mediaService, $scope, $window) {
var vm = this;
$scope.pdfUrl = 'http://localhost:3787/NCCN_Evidence_Blocks_Melanoma.pdf';
$scope.options = { mouseZoom: false, mousePan: false };
Please tell me, if you need more informations and thank you for your help.

Max upload size for ASP.MVC CORE website

How can I set maximum upload size for an ASP.NET CORE application?
In the past I was able to set it in web.config file like this:
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="52428800" />
</requestFiltering>
</security>
</system.webServer>
Two ways to do that:
1.Using application wise settings - in the > configure services method.
services.Configure<FormOptions>(options =>
{
options.MultipartBodyLengthLimit = 52428800;
});
2.Using RequestFormSizeLimit attribute - for specific actions. - It is not yet available in official package
Unofficial
You can configure the max limit for multipart uploads in the ConfigureServices method:
public void ConfigureServices(IServiceCollection services)
{
services.Configure<FormOptions>(options =>
{
options.MultipartBodyLengthLimit = 52428800;
});
services.AddMvc();
}
You can also configure the MaxRequestBufferSize by using services.Configure<KestrelServerOptions>, but it looks like this is going to be deprecated in the next release.

Is there a way to configure Serilog sub loggers via configuration file?

Currently I have all configuration written in code. I use subloggers for filtering and changing the storage of logging. Is there any way to do it from configuration file. Because I want to have a separate config file for every context in solution.
If the number of sub-loggers is fixed at build time, you can use configuration prefixes to do this:
Log.Logger = new LoggerConfiguration()
.ReadFrom.AppSettings() // default file
.WriteTo.Logger(lc => lc
.ReadFrom.AppSettings(filePath: "other1.config"))
.WriteTo.Logger(lc => lc
.ReadFrom.AppSettings(filePath: "other2.config"))
.CreateLogger();
There's no support in Serilog.Settings.AppSettings yet, but in theory there's nothing preventing it being added if someone's able to implement it.
Try this
Startup.cs / Global.asax.cs
Log.Logger = new LoggerConfiguration()
.WriteTo
.Logger(x => x.Filter
.ByIncludingOnly(logEvent => logEvent.Level == Serilog.Events.LogEventLevel.Error)
.ReadFrom
.AppSettings("error"))
.WriteTo
.Logger(x => x.Filter
.ByIncludingOnly(logEvent => logEvent.Level == Serilog.Events.LogEventLevel.Information)
.ReadFrom
.AppSettings("info")).CreateLogger()
Web.Config
<add key ="error:serilog:using:RollingFile" value="Serilog.Sinks.RollingFile"/>
<add key ="error:serilog:write-to:RollingFile.pathFormat" value="C:\log\error {Date}.txt"/>
<add key ="error:serilog:write-to:RollingFile.formatter" value="Serilog.Formatting.Json.JsonFormatter"/>
<add key ="info:serilog:using:RollingFile" value="Serilog.Sinks.RollingFile"/>
<add key ="info:serilog:write-to:RollingFile.pathFormat" value="C:\log\info {Date}.txt"/>
<add key ="info:serilog:write-to:RollingFile.formatter" value="Serilog.Formatting.Json.JsonFormatter"/>

ASP.NET MVC5 Customised Inbound Routing

I'm "playing" around with custom inbound URL routing and have came across a problem.
When I pass my custom route a URL to examine, that ends in *.+, my class is not fired when i submit the request.
An example URL would be "~/old/windows.html"
When I step through this in the debugger, my RouteBase implementation doesn't fire. If i edit the url that i pass to the constructor of my route to try to match against "~/old/windows", my implemetation is fired as expected.
Again, If i change the url ro examine to "~/old/windows." the problem reoccurs.
My Route Implementation is below :-
public class LegacyRoute : RouteBase
{
private string[] _urls;
public LegacyRoute(string[] targetUrls)
{
_urls = targetUrls;
}
public override RouteData GetRouteData(HttpContextBase httpContext)
{
RouteData result = null;
string requestedURL = httpContext.Request.AppRelativeCurrentExecutionFilePath;
if (_urls.Contains(requestedURL, StringComparer.OrdinalIgnoreCase))
{
result = new RouteData(this, new MvcRouteHandler());
result.Values.Add("controller", "Legacy");
result.Values.Add("action","GetLegacyURL");
result.Values.Add("legacyURL", requestedURL);
}
return result;
}
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
return null;
}
}
In the RoutesConfig file I have registered my route like so :-
routes.MapMvcAttributeRoutes();
routes.Add(new LegacyRoute(new[]{"~/articles/windows.html","~/old/.Net_1.0_Class_Library"}));
Can anyone point out why there is a problem?
By default, the .html extension is not handled by .NET, it is handled by IIS directly. You can override by adding the following section in Web.config under <system.webServer> -
<handlers>
<add name="HtmlFileHandler" path="*.html" verb="GET" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
As pointed out here. The above will route EVERY .html file request to .NET, you might want to be more specific by providing a more complete path if you don't want your routing to handle every .html file.
I've found the problem, and I'm sure this will help out a lot of fellow developers.
The problem is with IIS Express that is running via Visual Studio.
There is a module configured in the applicationhost.config called :-
UrlRoutingModule-4.0
This is how it looks in file :-
<add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" preCondition="managedHandler,runtimeVersionv4.0" />
You need to set the preCondition Parameter to "".
To do this :-
Run you app via Visual Studio
Right click on IIS Express in your system tray, select "Show All Applications"
Click on the project you wish to edit, then click the config URL.
Open the file with Visual Studio, Locate the module and ammend.
Hope this helps anyone else, who ran into a similar problem.

Resources