Miniprofiler.MVC5: "profiler/results" 404 not found when deployed on IIS - asp.net-mvc-5

To use Miniprofiler in an MVC 5 application, I followed all the steps mentioned in MiniProfiler for .NET Documentation for ASP.NET
with these differences in Global.aspx:
protected void Application_Start()
{
MiniProfiler.Configure(new MiniProfilerOptions
{
Storage = new MemoryCacheStorage( new System.TimeSpan(1,0,0) ),
ResultsAuthorize = request => {return true;},
// The rest of the options go here
.
.
}
.AddViewProfiling()
);
}
protected void Application_BeginRequest()
{
// For all requests, not only local
MiniProfiler.StartNew();
}
and in Config:
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<!-- hendlers go here as described in the documentation -->
...
</system.webServer>
The rest is identical to the documentation.
The profiler works locally as expected. But when deployed on Windows server 2016 IIS 10, I get 404 not found error for "profiler/results", and when I navigate to "profiler/results-index", an empty table is displayed with headers only, i.e. no rows for results.
Those images are from the browser using Inspect:

Related

Url scheme based link does not seem to work in Blazor MAUI

I am building an app with .NET MAUI and Blazor, that initially targets iOS, but should also support Android, in a next release.
I have, in my Info.plist file added an entry myapp in the CFBundleURLSchemes array. And I use this as a redirect uri from our web portal (open in app, with the href myapp://settings/profile).
What happens, is that iOS comes and asks confirmation if that link can be opened with my app. (see screenshot).
But it just opens the app to the page that was previously open. It does not navigate to the Blazor page that is registered with the #page "/settings/profile" directive.
Is this something that is not supported? Or do I have to add something around the routing, here?
Current logic
With the following code in AppDelegate (for iOS), I can intercept that call and access the requested Url from that scheme-link.
public override bool OpenUrl(UIApplication application, NSUrl url, NSDictionary options)
{
AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(url);
if (url?.Scheme?.Equals(myScheme, StringComparison.InvariantCultureIgnoreCase) ?? false)
{
var pageUrl = url.ToString().Replace($"{myScheme}://", "");
PageSettings.RequestedUri = pageUrl; // This is the static class/var I want to leverage in BlazorWebView
return base.OpenUrl(application, new NSUrl( pageUrl), options);
}
return base.OpenUrl(application, url, options);
}
However, I don't seem to find out how I can enforce the BlazorWebView to navigate to the right uri.
As I know, there is no way to do this currently with MAUI Blazor.
Refer to the documentation maui-blazor documentation, the .NET MAUI Blazor hybrid project template isn't a Shell-based app.
If you want to route to #page "/settings/profile", you could describe some information about where to go in AppDelegate, then set some staic and launch a simple page (MAUI PAGE), get the value and show the Blazor page.
public override bool OpenUrl (UIApplication app, NSUrl url, string sourceApp, NSObject annotation){
if (url.BaseUrl.Host.Equals ("app.myapp.io")) {
UIViewController page = new TargetPage().CreateViewController();
}
return true;
}
Set the homepage to your needs
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:BlazorDemo"
x:Class="BlazorDemo.TargetPage"
BackgroundColor="{DynamicResource PageBackgroundColor}">
<BlazorWebView x:Name="blazorWebView" HostPage="wwwroot/profile.html">
<BlazorWebView.RootComponents>
<RootComponent Selector="#app" ComponentType="{x:Type local:Main}" />
</BlazorWebView.RootComponents>
</BlazorWebView>
</ContentPage>

502 error upload csv file to web api

I have an Angular5 user interface with a file upload function. The user clicks a button and selects a file and the file is sent to the web api (asp.NET Core) method for processing.
This works fine with smaller files, but with larger files the request times out with a 502 error.
I can see the request always timesout at 120 seconds. (NOTE: I am hosting via node in development and via IIS in production).
In the case of large files I need to extend this timeout to a larger value. I've tried to achieve this in a number of ways:
Request Header - Timeout of request in angular code. I used the following code to try to set the timeout header value but it doesn't effect the 120 seconds:
export class AuthTokenInterceptor implements HttpInterceptor {
constructor(private authContext: AuthContext) {
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const authHeaderValue = this.authContext.getAuthenticationHeaderValue(req.url);
if (authHeaderValue) {
const authReq = req.clone({ headers:
req.headers.set('Authorization', authHeaderValue)
.set('Timeout', '100000000000000000') });
return next.handle(authReq);
}
return next.handle(req);
} }
web.config - I've tried setting the httpRuntime timeout value in the web.config file to the following (but still times out at 120 seconds):
Within IIS - I've tried setting the configuration of the "Limits" property in IIS and again, still times out at 120 seconds (and this has no relevance when I'm running through node server).
Has anyone been able to modify this 120 seconds in their Angular(2+) app requests?
Thanks for any pointers in advance!
NOTE: just for completeness, here's my asp.net core, controller method for uploading:
[HttpPost("Upload")]
public async Task<IActionResult> UploadAsync(IFormFile file)
{
// Ensure the file has contents before processing.
if (file == null || file.Length == 0)
throw new ApiException("Csv file should not be null", HttpStatusCode.BadRequest)
.AddApiExceptionResponseDetails(ErrorTypeCode.ValidationError, ErrorCode.BelowMinimumLength, SOURCE);
// Ensure the file is not over the allowed limit.
if (file.Length > (_settings.MaxCsvFileSize * 1024))
throw new ApiException("Max file size exceeded, limit of " + _settings.MaxCsvFileSize + "mb", HttpStatusCode.BadRequest)
.AddApiExceptionResponseDetails(ErrorTypeCode.ValidationError, ErrorCode.ExceedsMaximumLength, SOURCE);
// Ensure the file type is csv and content type is correct for the file.
if (Path.GetExtension(file.FileName) != ".csv" ||
!Constants.CsvAcceptedContentType.Contains(file.ContentType.ToLower(CultureInfo.InvariantCulture)))
throw new ApiException("Csv content only accepted").AddApiExceptionResponseDetails(ErrorTypeCode.ValidationError, ErrorCode.Invalid, SOURCE);
// Read csv content.
var content = await file.ReadCsvAsync<OrderCsvResponseDto>() as CsvProcessedResponseDto<OrderCsvResponseDto>;
await ProcessBulkUpload(content);
// Return information about the csv file.
return Ok(content);
}
Note - when I run the web api via IIS Express then it times out, I've run it using the command host and it doesn't time out - seem's like this may be related to an IIS setting of sorts. The web api doesn't have a web.config file due to the new version of ASP.net Core I'm using but this piece of code doesn't seem to have any bearing on IIS Express when I run through it:
var host = new WebHostBuilder()
.UseStartup<Startup>()
.UseKestrel(o => {
o.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(10);
o.ShutdownTimeout = TimeSpan.FromMinutes(10);
o.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(10);
})
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseApplicationInsights()
.Build();
I will post this here in case anyone else comes across the same problem I was having. It turns out that running in IIS Express (or hosted IIS) that the config setting overrides whatever you have in code (maybe this is because the newer version of .net Core doesn't have a web.config file in the project - I'm not sure).
Anyway, I worked around this problem by carrying out the following steps:
Open IIS Express in your taskbar
Click on the app you are running (and wish to extend the request timeout for).
Clicking the app shows the config file of the application. Double click to open the config file.
Apply the following setting to the aspNetCore section:
requestTimeout="00:20:00"
Example:
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" forwardWindowsAuthToken="false" requestTimeout="00:20:00" stdoutLogEnabled="false" />
<httpCompression>
<dynamicCompression>
<add mimeType="text/event-stream" enabled="false" />
</dynamicCompression>
</httpCompression>
</system.webServer>
And that's it!
NOTE: I am hosting the app in PaaS ASE - so cant configure IIS directly here. My solution for this was now to add a web.config file to the api project, and apply my setting within it. The build process honours the web.config you've got already instead of generating one on the fly and it will keep the changes needed. In my case, the web.config looked like this:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" forwardWindowsAuthToken="false" requestTimeout="00:20:00" stdoutLogEnabled="false" />
</system.webServer>
</configuration>
Hopefully this helps others!

NLog with DNX Core 5.0

I am attempting to implement NLog logging using ASP.Net 5 and MVC 6. Be default, both DNX 451 and DNX Core 50 are included in the project template.
I am attempting to implement NLog Logging by following the example here.
However, in the sample app, there is the following line -
#if !DNXCORE50
factory.AddNLog(new global::NLog.LogFactory());
#endif
And if I run the app, this line never gets hit because the mvc application has dnx core 50 installed by default.
Is there any loggers that are available for DNX Core 50? If not, what purpose does dnx core serve in the default mvc app - is it actually needed?
Edit: If I remove the #if !DNXCORE50.... line above, I get a the following error -
DNX Core 5.0 error - The type or namespace name 'NLog' could not be found in the global namespace'
DNX Core 5.0 is only necessary if you want the cloud-optimized cross-platform version of the .Net framework; if you still plan on using the MVC app within only a Windows environment, you can remove your dnxcore50 framework reference from your project.json.
NLog for .NET Core (DNX environment) is currently available in version 4.4.0-alpha1.
Steps:
Create NLog.config
<?xml version="1.0" encoding="utf-8" ?>
<targets>
<target xsi:type="ColoredConsole" name="ToConsole" />
</targets>
<rules>
<logger name="*" minlevel="Info" writeTo="ToConsole" />
</rules>
Load and parse configuration
private static ILogger _logger;
public static void LoggerSetup()
{
var reader = XmlReader.Create("NLog.config");
var config = new XmlLoggingConfiguration(reader, null); //filename is not required.
LogManager.Configuration = config;
_logger = LogManager.GetCurrentClassLogger();
}
public static void Main(string[] args)
{
LoggerSetup();
// Log anything you want
}
When dealing with the MVC tooling in MVC6 (dnx stuff), the answer to this is very fluid.
In order to get NLog to work with my web app, I had to do a couple steps:
-> Big thanks to two NLog discussions(here and here)
I just needed to add the configuration setup in my Startup.cs's constructor:
public Startup(IHostingEnvironment env)
{
// Set up configuration sources.
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddEnvironmentVariables();
// Set up logging configuration
// from: https://github.com/NLog/NLog/issues/641
// and: https://github.com/NLog/NLog/issues/1172
var reader = XmlTextReader.Create(File.OpenRead(Path.Combine(builder.GetBasePath(),"NLog.config"))); //stream preferred above byte[] / string.
LogManager.Configuration = new XmlLoggingConfiguration(reader, null); //filename is not required.
log.Info("NLogger starting");
Configuration = builder.Build();
}
I consider this a bit of a stop-gap as Microsoft is introducing a new Logging interface (that I hope will end up being like SLF4J.org is in Java). Unfortunately, documentation on that is a bit thin at the time I'm writing this. NLog is working diligently on getting themselves an implementation of the new dnx ILoggingProvider interface.
Additional information about my project setup
My NLog.config file is located in the project root folder, next to
the project.json and appsettings.json. I had to do a little digging
inside AddJsonFile() to see how they handled pathing.
I used yeoman.io and their aspnet generator to set up the web project.
Version of NLog, thanks to Lukasz Pyrzyk above:
"NLog": "4.4.0-alpha1"

Opening Default document on IIS

I've a deployed ASP.NET Web API with a website on the same folder that consume it.
When I type the URL on the Browser such as http://domain.com/ it returns a 404, but if I type http://domain.com/index.html it works!
I wanna know if there's a way to configure it on Web API route, define a default route for it, redirecting to my http://domain.com/index.html when I type http://domain.com/
I've tried ti put this on Web.Config without success:
<defaultDocument enabled="true">
<files>
<add value="/index.html" />
</files>
</defaultDocument>
Also, I set up my IIS to only accept index.html default document. no success =/
Any ideas?
I'm not sure if this is the best way to achieve this, I just edited my RouteConfig.cs such this:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "index.html"
);
}
}
Now I can get http://domain.com works perfectly!
I'd love If anyone have a best way to achieve this!
Well, It is situational, for what you are doing that is fine.
I have done things like:
routes.IgnoreRoute("");
I typically still end up with problems when the default mvc portion of web api is hit and so for me I end up doing this
public ActionResult Index()
{
string filePath = Server.MapPath("~/contact.html");
if (System.IO.File.Exists(filePath))
{
return File(filePath, "text/html");
}
return View();
}

ASP.NET MVC 4 cookie disappears

I have an ASP.NET application that sends an authentication cookie to an ASP.NET MVC application, used as an back office application.
I've added a global filter that checks every controller action for the authentication cookie. If the cookie exists, it allows the user to enter the page.
The code looks like this:
public class SecurityFilter : FilterAttribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationContext filterContext)
{
// TODO: For some reason .AUTHCookie cookie isn't exist in request context of filter,
HttpCookie cookie = filterContext.RequestContext.HttpContext.Request.Cookies[".AUTHCookie "];
if (cookie != null) {
From the other side I can see the cookie sent from the ASP.NET application in Application_BeginRequest event in the Global.asax file.
Where and why the cookie disappeared? In what part of the MVC Request-Handling pipeline was the cookie thrown away?
protected void Application_BeginRequest(object sender, EventArgs e)
{
var cookies = HttpContext.Current.Request.Cookies;
// HERE I CAN SEE BOTH cookies. In filter action only one cookie was found. The authentication cookie is thrown somewhere ...
}
I found a solution for my scenario. I've added a compatibilityMode="Framework45" into the machinekey in both applications and it's all working perfectly.
Note: If one of your applications is using an older versions of the .NET framework, you must explicitly configure your .NET 4.5 apps to use the earlier machine compatibility modes, or they will not be able to encrypt/decrypt the forms authentication ticket.
Just to remind you my scenario:
WebForms ASP.NET 4.5
<machineKey compatibilityMode="Framework45" decryption="AES" validation="SHA1" decryptionKey="your_key1" validationKey="your_keu2" />
<authentication mode="Forms">
<forms name="_authcookie" domain=".domain.com" loginUrl="Default.aspx?View=1" defaultUrl="Default.aspx?View=1" timeout="30" path="/" protection="All" slidingExpiration="true" enableCrossAppRedirects="true" />
</authentication>
MVC 4
<machineKey compatibilityMode="Framework45" decryption="AES" validation="SHA1" decryptionKey="your_key1" validationKey="your_keu2" />
<authentication mode="Forms">
<forms name="_authcookie" domain=".domain.com" defaultUrl="~/" timeout="30" path="/" protection="All" slidingExpiration="true" enableCrossAppRedirects="true" />
</authentication>
Possible values for the compatibility mode:
http://msdn.microsoft.com/en-us/library/system.web.configuration.machinekeysection.compatibilitymode.aspx

Resources