Glimpse throws NullReferenceException with EPiServer 7.1 MVC 4 - asp.net-mvc-4

I have an MVC 4 application built on top of EPiServer 7.1. EPiServer uses StructureMap as it's IoC framework, which may be related to my problems. Anyhow, this is what I have done:
Via "Manage Nuget Packages...", added "Glimpse Mvc4" to my project
Verified that web.config was updated as expected
Restarted my application
After adding Glimpse, all requests fail with a NullReferenceException, e.g., like this:
I have tried enabling Glimpse logging by commenting in 'logging level="Trace"' in the Glimpse-section of web.config, but can't find any logging in neither Windows event logs or log4net log files.
Ideas on how to troubleshoot further, or hints to a solution?

A workaround (thanks to #avanderhoorn!) is to add this to the "glimpse" section of web.config:
<glimpse defaultRuntimePolicy="On" endpointBaseUri="~/Glimpse.axd">
<tabs>
<ignoredTypes>
<add type="Glimpse.AspNet.Tab.Routes, Glimpse.AspNet"/>
</ignoredTypes>
</tabs>
<inspectors>
<ignoredTypes>
<add type="Glimpse.AspNet.Inspector.RoutesInspector, Glimpse.AspNet"/>
<add type="Glimpse.Mvc.Inspector.ModelBinderInspector, Glimpse.Mvc4"/>
</ignoredTypes>
</inspectors>
</glimpse>
This disables the two parts of Glimpse that break with EPiServer. As far as I can see, you still get the most useful parts available!

+1 the same here. What I found so far is that by adding Glimpse it augments all routes and replaces with it's own proxy classes for intercepting calls to routing.
EPiServer (and UrlResolver in particular) seems that don't like this case. The root cause for this exception is following method:
UrlResolver.GetVirtualPath(ContentReference contentLink, string language, RouteValueDictionary routeValues, RequestContext requestContext)
What it doesn't like is fact that there is no route of type ContentRoute in the routing table:
foreach (RouteBase base2 in from r in this._routes
where (bool) (r is ContentRoute)
select r)
{
...
if(...)
{
return virtualPath;
}
}
return null;
And after returning null to the caller NullReferenceExpcetion occours in:
UrlExtensions.MapUrlFromRoute(RequestContext requestContext, RouteCollection routeCollection, string url)
Seems like patch from EPiServer should be awaited.

Related

Getting exception details from failing ASP.NET Core Configure() method in Azure

I'm hosting an ASP.NET Core app in a Windows Azure Web Site. I'm wondering how to get details of an exception occuring in the Startup.Configure() method? All I see is An error occurred while starting the application..
One thing that DOES work is adding an app setting of ASPNETCORE_ENVIRONMENT="Development".
Then I get System.Exception... at X.Startup.Configure() as expected.
But this is not a feasible solution. Azure is my Staging environment, and I'm already using the environment concept to substitute my connection strings (as suggested in almost every ASP.NET Core documentation I have ever read).
Things I have tried without any effect:
Adding app.UseDeveloperExceptionPage() (not surrounded by any if statement).
Adding <customErrors mode="Off"/> to Web.config, as suggested here https://stackoverflow.com/a/29539669/268091
Adding ASPNET_DETAILED_ERRORS="true" to Web.config, as suggested here https://stackoverflow.com/a/32094245/268091
Enabling Detailed error messages in Azure portal / Diagnostics logs
Adding a try-catch, writing a manual response, as suggested here https://stackoverflow.com/a/29524042/268091
Deleting everything and redeploying.
Is there really no other way to achieve this, than hijacking the environment concept altogether?
I don't know if this would work for you, but we've decided to report these using Application Insights.
public void Configuration(IAppBuilder app)
{
var ai = new Microsoft.ApplicationInsights.TelemetryClient();
ai.TrackEvent("Application Starts");
try
{
//Amazing code here
}
catch ( Exception ex )
{
ex = new Exception("Application start up failed.", ex);
ai.TrackException(ex);
throw;
}
}

Nservicebus disable default logger in web.config

I'm using the DefaultFactory LogManager for Nservicebus v5. I'm happy with this but was hoping to be able to disable via the web.config.
I use web.config settings, as found in the help docs
<configSections>
<section name="Logging" type="NServiceBus.Config.Logging, NServiceBus.Core" />
</configSections>
<Logging Threshold="Debug" />
I'd prefer not to set the threshold as fatal. I was hoping for a "None" or Disabled="true"
Also can the directory path be set web.config?
Update: Why would we want to ignore errors?
The short is we don't really have write permission on the servers.
The long is this isn't 100% true.
Our systems is moving towards microservices, the problem with this is that decentralized logging is a tracing/visualization nightmare.
So we moved flow tracing, exceptions, and limited tracing to a centralized system.
Programming Entry points (aka message Handlers, web api endpoints, etc) are nearly always wrapped in a try catch log throw on each handler, this covers all our programming errors. This isn't anything really that different to normal.
The centralized logging location sets of all the nice red flashing real time alarms one could wish for.
Which leaves only configuration type error left like missing queues, bad assembly bindings, faulty config files, or more runtime style stuff like IoC wiring (outside of the handler code).
With the centralized logging and monitoring of the error quests, it is fairly easy to detect when the service is broken and if it is then we turn on logging, restart, try the faulty issue, and fix.
Guaranteed delivery will take care of everything else once it is up again :D Gone are the days of 150mb log files spread across 10 different servers.
The simplicity of DefaultFactory was nice, as was not needing another nuget package and associated configuration.
Is this the correct way forward. Many would argue no.
Could we have done it better? yes we could implement the common logger interface and pass it into NServiceBus but we arn't quiet there just yet and the win isn't critical atm.
A side note: One really really nice thing about the way we log is that in our backoffice tool we have been able to simply show the flow for each "order", similar to using a correlation id in greylog.
Since this was not considered a likely scenario it does not have a first class API. But you can achieve this via passing in a null logger from any of the common logging libraries (NLog, Log4net, CommonLogging). I assume you are using one of these in your website.
So take NLog for example.
Install-Package NServiceBus.NLog
The in your webconfig
<appSettings>
<add key="disableLogging" value="true"/>
</appSettings>
Then in your global startup
if (ConfigurationManager.AppSettings.Get("disableLogging") == "true")
{
LoggingConfiguration config = new LoggingConfiguration();
LogManager.Configuration = config;
NServiceBus.Logging.LogManager.Use<NLogFactory>();
}
This is leveraging the approach documented here http://docs.particular.net/nservicebus/logging-in-nservicebus#nlog

Serving static files and falling back to MVC routing

I have an ASP.NET MVC 4 application running under IIS 8.5. My previous understanding/experience of these scenarios in MVC is that if a static file exists, it will be served. If it doesn't exist, the path will be sent through MVC routing. This is the desired behaviour, but doesn't seem to be happening.
By default if I create a catchall route at /blah.html and no corresponding static file, IIS serves up a 404 (courtesy of the StaticFile handler). The MVC route is never hit. If the file exists, it is served.
So, I did some Googling and chatting to colleagues and came up with the answer as posted here:
https://stackoverflow.com/a/14327897/1043198
In goes the handler:
<add name="ApiURIs-ISAPI-Integrated-4.0" path="*" type="System.Web.Handlers.TransferRequestHandler" verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" preCondition="integratedMode,runtimeVersionv4.0" />
Great! The request now hits the MVC app and my dynamic content is served as expected. Except now, when I put a physical file in place, I get an error again. An uninformative 500 error with the following information (and nothing else):
Module: ManagedPipelineHandler
Notification: ExecuteRequestHandler
Handler: ApiURIs-ISAPI-Integrated-4.0
Error Code: 0x800703e9
What's going on? Why does IIS not fall back to my MVC app when static files don't exist and how come when I fix that, the inverse occurs and static files are no longer served properly? I'm fairly sure this has always been default behaviour in the past.
App pool is running in Integrated mode, CLR v4.0.
After finding various answers and blog posts suggesting enabling runAllManagedModulesForAllRequests, it seems that this - while it works - isn't the right approach.
RAMMFAR does exactly what it says on the tin and runs all requests (including those for "unmanaged" static resources) through all managed modules, which has a performance overhead and can also cause unusual side-effects depending on the modules enabled and the requests run through them.
Turns out the only module required to solve this problem is the UrlRoutingModule which, when the precondition is removed, causes all static resources to be run through MVC routing (when no static file exists):
<remove name="UrlRoutingModule" />
<add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule"
preCondition="" />

mini profiler WCF

I am trying to use mini profiler with WCF.
I keep getting a 404 error:
http://website/mini-profiler-resources/results
There are no results being returned.
I am using two versions of the mini profiler. The NUGET version which doesn't include support for WCF works just fine.
I downloaded the git version so that I can use the WCF integration.
I note that if I run the test project included in the sources 'Sample.Mvc' the same error occurs when the home page is executed, but not for some of the links. I cannot seem to get results for any of my own web site pages. The same 404 occurs.
I have downloaded the master version. I am using .NET 4.0 and studio 2010.
I have the following in the config file, I have tried with and without the handlers.
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules runAllManagedModulesForAllRequests="true" />
<handlers>
<add name="MiniProfiler" path="mini-profiler-resources/*" verb="*" type="System.Web.Routing.UrlRoutingModule" resourceType="Unspecified" preCondition="integratedMode" />
</handlers>
</system.webServer>
I am definitely calling the start and stop methods.
StackExchange.Profiling.MiniProfiler.Stop();
I have read this: MvcMiniProfiler results request giving 404 in Asp.Net MVC app
It did not help.
I have found a clue as to the problem
The following code in miniprofiler is returning NotFound
The profiler is expecting some kind of guid value to be present, and it isn't.
private static string Results(HttpContext context) {
// this guid is the MiniProfiler.Id property
Guid id;
if (!Guid.TryParse(context.Request["id"], out id))
return isPopup ? NotFound(context) : NotFound(context, "text/plain", "No Guid id specified on the query string");
temporary fix
I took out the code above, and just collected the first guid out of storage, and this fixed the problem. I think this code needs cleaning up. I need to learn GIT, and then try and clean it up myself.
var id = MiniProfiler.Settings.Storage.List(10).FirstOrDefault();
Can you see .../mini-profiler-resources/results-index ?
Handler not required btw. There is a comma in your link but assume that is just a question typo.
Are you calling start last thing in the Application_BeginRequest() and stop in Application_EndRequest()
Have you set GlobalFilters.Filters.Add(new ProfilingActionFilter());?
and are you using WebActivator with a MiniProfilerPackage and MiniProfilerStartupModule
Think I need to tidy up my own implementation as looks like I have some unnecessary cruft.

Visual Studio 2012 install broke my 2010 WCF project

I've installed VS 2012 and am successfully using it on some web projects, but something with it has caused my web service project to break. I'm still using VS 2010 on the web service project and have not opened it in 2012.
Everything compiles and works correctly except when it tries to create an instance of a class in my referenced weblog project, then it throws this error:
This method or property is not supported after HttpRequest.GetBufferlessInputStream has been invoked.
I can not find anywhere in the project where GetBufferlessInputStream is used explicitly.
If I jump over the weblog code, everything executes correctly.
I can't find anyone else who has received this error to try and narrow it down, any ideas where to start?
Stack
at System.Web.HttpRequest.get_InputStream()
at OAS.Web.Log.WebEvent..ctor(EventType type, HttpContext context, String applicationName)
at OAS.Web.Log.WebTrace..ctor(HttpContext context, String applicationName)
at OAS.Web.AdvisorServices.Extensions.OperationLoggerParameterInspector.BeforeCall(String operationName, Object[] inputs) in C:\SourceControl\OAS\IM.NET3.0\Web\AdvisorServices\OAS.Web.AdvisorServices.Extensions\OperationLogger\OperationLoggerParameterInspector.cs:line 54
**EDIT - Bonus Question
Why are these Framework 4.5 properties affecting my 4.0 solution?
Note : This issue has been fixed in .net 4.5.1. You can see the fix with 4.5.1. Once you have .net 4.5.1 add the following appSetting to switch back to the old behavior.
<configuration>
<appSettings>
<add key="wcf:serviceHostingEnvironment:useClassicReadEntityBodyMode" value="true" />
</appSettings>
</configuration>
Here is how you can create a HttpModule to force ReadEntityBodyMode to be "classic" : http://blogs.msdn.com/b/praburaj/archive/2012/09/13/accessing-httpcontext-current-request-inputstream-property-in-aspnetcompatibility-mode-throws-exception-this-method-or-property-is-not-supported-after-httprequest-getbufferlessinputstream-has-been-invoked.aspx
To answer your other question (Why are these Framework 4.5 properties are effecting my 4.0 solution?):
.net 4.5 is an in-place upgrade of .net 4.0. So even if your project is targeting 4.0, since VS 2012 installs 4.5 runtime, some of the 4.5 behaviors take effect.
EDIT
Blog Entry:
In .net 4.5 WCF leveraged the buffer less input stream for scalability benefits. As a result when you try to access the HttpContext.Current.Request.InputStream property you may end up with the below exception, as the InputStream property tries to get you handle to the Classic stream as they both are incompatible.
“This method or property is not supported after
HttpRequest.GetBufferlessInputStream has been invoked.”
If you had a WCF 4.0 app which worked perfectly but on upgrading your .net framework to 4.5 you notice the service failing on accessing this property, here is the way to work-around the issue:
Add a simple HttpModule in the same WCF project which will access the InputStream property for each request before WCF reads it so that it will enforce the HttpContext.Request.ReadEntityBody to be "Classic" and will ensure compatibility.
public class WcfReadEntityBodyModeWorkaroundModule : IHttpModule
{
public void Dispose() { }
public void Init(HttpApplication context) {
context.BeginRequest += context_BeginRequest;
}
void context_BeginRequest(object sender, EventArgs e) {
//This will force the HttpContext.Request.ReadEntityBody to be "Classic" and will ensure compatibility..
Stream stream = (sender as HttpApplication).Request.InputStream;
}
}
Register this module in your web.config by adding these lines in <configuration> <modules> setting.
<system.webServer>
<modules>
<!-- Register the managed module -->
<add name="WcfReadEntityBodyModeWorkaroundModule" type="MyAssembly.WcfReadEntityBodyModeWorkaroundModule, MyAssembly" />
</modules>
If you are using an app pool in classic mode, you will need to add the module to this section in the web.config:
<system.web>
<httpModules>
<add name="WcfReadEntityBodyModeWorkaroundModule" type="MyAssembly.WcfReadEntityBodyModeWorkaroundModule, MyAssembly" />
</httpModules>
If your project cannot be modified, then you can write this Http module in a separate assembly, GAC it separately and register this module in the web.config.
Now try accessing the service it should succeed for you!