asp.net mvc 3 and elmah.axd - yet another 404 - asp.net-mvc-3

Hi all I know that this has been posted as a prior question several times, but I've gone through each question and their proposed solutions and I'm still not able to surmount my 404 issue. I'm running Elmah 1.1 32-bit. I've referred to ASP.NET MVC - Elmah not working and returning 404 page for elmah.axd but I haven't had any luck after applying the suggestions.
I'm running ASP.NET MVC 3. Here's my web.config:
...
<httpHandlers>
<add verb="POST,GET,HEAD" path="elmah.axd" type="Elmah.ErrorLogPageFactory, Elmah" />
</httpHandlers>
<httpModules>
<add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah"/>
<add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" />
<add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah" />
</httpModules>
...
<errorLog type="Elmah.SqlErrorLog, Elmah"
connectionStringName="dbconn" />
<errorFilter>
<test>
<jscript>
<expression>
<![CDATA[
// #assembly mscorlib
// #assembly System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
// #import System.IO
// #import System.Web
HttpStatusCode == 404
|| BaseException instanceof FileNotFoundException
|| BaseException instanceof HttpRequestValidationException
/* Using RegExp below (see http://msdn.microsoft.com/en-us/library/h6e2eb7w.aspx) */
|| Context.Request.UserAgent.match(/crawler/i)
|| Context.Request.ServerVariables['REMOTE_ADDR'] == '127.0.0.1' // IPv4 only
]]>
</expression>
</jscript>
</test>
</errorFilter>
I have my .axd routes ignored using:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
I'm running the site on IIS7, 32 bit mode enabled. I've tried many different configuration options but all to no avail. Any ideas?
Thanks
Shan

My bad. My .axd ignore route rule was ordered after the default route mapping. The default route mapping rule was matching the URL elmah.axd. I guess I didn't realize that the ignore rules had to be listed above this route. Thanks everyone for your help!
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new
{
controller = "Home",
action = "Index",
id = UrlParameter.Optional
} // Parameter defaults
);
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
Simply moving routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); before the Default route mapping resolved this issue.

Copy the .dll to your bin and reference... add the elmah defaults to configSections
Don't put the handler inside the system.webServer as mentioned above, try system.web section like this instead in your web.config.
<system.web>
<httpHandlers>
<add verb="POST,GET,HEAD" path="elmah.axd" type="Elmah.ErrorLogPageFactory, Elmah" />
</httpHandlers>
</system.web>
just leave your global.asax as default:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
browse to the axd locally
then if working, lock it down with the config section Gedas mentioned above.

Have you tried this?
<configuration>
<system.webServer>
<handlers>
<add name="elmah" verb="POST,GET,HEAD" path="elmah.axd" type="Elmah.ErrorLogPageFactory, Elmah" />
</handlers>
</system.webServer>
</configuration>
also make sure to secure elmah.axd location from regular users:
<location path="elmah.axd">
<system.web>
<authorization>
<allow roles="Admin" />
<deny users="*" />
</authorization>
</system.web>
</location>

I was getting a 404 error due to the SQLServer Compact database being over the default max file size. Just deleted the SDF data file and 404 went away.

In asp.net mvc 3 global.asax.cs file
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
//filters.Add(new HandleErrorAttribute());
}
HandleErrorAttribute will swallow all exceptions, leaving nothing for ELMAH to handle.
See Joe's blog http://joel.net/wordpress/index.php/2011/02/logging-errors-with-elmah-in-asp-net-mvc3-part1/

Related

How to config HTTPPlatformHandler of IIS for Server Sent Event (SSE, EventStream)

Currently I have program that provide SSE as a service, and I have to deploy on IIS. But its does not work correctly,
Here is the result when I run .exe without IIS.
data: Hello, world
But when its run behind IIS, Browser was stuck on loading.
I have to flush event Hello, world thousand times to make IIS flush result to browser and it's flush instantly instead of incremental update like SSE use to be.
Here is my web.config
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<handlers>
<add name="httpplatformhandler" path="*" verb="*" modules="httpPlatformHandler" resourceType="Unspecified" />
</handlers>
<httpPlatform processPath=".\sse_server.exe"
arguments="-port=%HTTP_PLATFORM_PORT% -environment development"
stdoutLogEnabled="false"
requestTimeout="00:05:00"
stdoutLogFile=".\sse_server_log">
</httpPlatform>
<urlCompression doStaticCompression="true" doDynamicCompression="false" />
<caching enabled="false" enableKernelCache="false" />
</system.webServer>
</configuration>
Here is my go code
func SSEHello(rw http.ResponseWriter, flusher http.Flusher) {
rw.Header().Set("Content-Type", "text/event-stream; charset=utf-8")
rw.Header().Set("Cache-Control", "no-cache")
rw.Header().Set("Connection", "keep-alive")
rw.WriteHeader(http.StatusOK)
for i := 0; i < 1000; i++ {
rw.Write([]byte("data:Hello, world\n\n"))
flusher.Flush()
time.Sleep(time.Millisecond * 100)
}
}
Actually HttpPlatformHandler has 8kb output buffer , so my message is not sent out immediately.
I have to change HttpPlatformHandler to ASP.NET Core Module,
so web.config must update to this.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath=".\sse_server.exe" />
</system.webServer>
</configuration>
And to start go 's application as aspNetCore on iis, the application need to get environment variable name ASPNETCORE_PORT then start http service on that port.
port := os.Getenv("ASPNETCORE_PORT")
http.ListenAndServe(":"+port, nil)
That's all!

rewrite URl from www.m.example.com to m.example.com

I am trying to do a redirect in ASP.NET web.config which contains like www.m.example.com to m.example.com; I have tried different approaches but wasn't able to do it.
Instead of the web.config, you could apply the following to your page:
<script runat="server">
private void Page_Load(object sender, System.EventArgs e)
{
Response.Status = "301 Moved Permanently";
Response.AddHeader("Location","http://www.new-location.com");
}
</script>
Read more here
If you do still want to use the web.config file, you can do the following:
Open web.config in the directory where the old pages reside
Then add code for the old location path and new destination as follows:
<configuration>
<location path="services.htm">
<system.webServer>
<httpRedirect enabled="true" destination="http://domain.com/services" httpResponseStatus="Permanent" />
</system.webServer>
</location>
<location path="products.htm">
<system.webServer>
<httpRedirect enabled="true" destination="http://domain.com/products" httpResponseStatus="Permanent" />
</system.webServer>
</location>
</configuration>

Downloading file with webapi

I'm trying to write an action in a webapi controllers to allow downloading a file.
But for some strange reason, the code doesn't works.
Here is my code:
<RoutePrefix("api/files")>
Public Class PermitFilesController
Inherits ApiController
<Route("download")>
public function GetFile() As HttpResponseMessage
Dim fStream as FileStream = File.Open("C:\Projects\1234.pdf", FileMode.Open, FileAccess.Read )
Dim response = Request.CreateResponse(HttpStatusCode.OK)
response.Content = new StreamContent(fStream)
'response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
'response.Content.Headers.ContentDisposition.FileName = Path.GetFileName(fStream.Name)
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf")
return response
End Function
I try to download simply using the url in browser:
localhost:<myport>/api/files/download
The error (in Chrome ) is Error code: ERR_CONNECTION_RESET
In FF, it is even stranger: it redirects me to www.localhost.com:/... with the same error - connection reset by host
I put a breakpoint in my code, and I noticed the code gets called twice (as soon as I exit from trace from last line, it gets called again to the first line).
I have several other actions in this controller, and they all work ok.
Anyone having any idea what am I doing wrong?
EDIT
I started Fiddler, and now my browser shown this error:
[Fiddler] ReadResponse() failed: The server did not return a response
for this request. Server returned 0 bytes.
EDIT
I want to mention that webapi is integrated into a legacy classic asp.net application
The initialization code is as follows:
In global.asax.Application_Start
WebApiHelper.Initialize
....
....
Public Class WebApiHelper
Public Shared Sub Initialize()
GlobalConfiguration.Configuration.MessageHandlers.Add(New BasicAuthMessageHandler() With { _
.PrincipalProvider = New MPNAuthProvider() _
})
AreaRegistration.RegisterAllAreas()
WebApiConfig.Register(GlobalConfiguration.Configuration)
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters)
RouteConfig.RegisterRoutes(RouteTable.Routes)
GlobalConfiguration.Configuration.EnsureInitialized()
End Sub
....
MPNAuthProvider is used to ensure authenticated access to some webapi controllers
Public Class MPNAuthProvider
Implements IProviderPrincipal
Public Function CreatePrincipal(username As String, password As String) As IPrincipal Implements IProviderPrincipal.CreatePrincipal
Dim userID As Integer = 0
If Not UserData.ValidateUser(username, password, userID) Then Return Nothing
Dim identity = New GenericIdentity(userID)
Dim principal = New GenericPrincipal(identity, {"User"})
Return principal
End Function
End Class
Anything else I should check to see what happens?
Thank you
Initial Solution
After suggestion from Julien Jacobs, I tested my code into a separate, stand alone webapi project, and indeed the code proved to be correct.
So I started to investigate the web.config.
And I found the following settings that I had to comment out:
<system.web>
....
<httpModules>
<add name="RadUploadModule" type="Telerik.Web.UI.RadUploadHttpModule" />
<add name="RadCompression" type="Telerik.Web.UI.RadCompression" />
</httpModules>
and
<modules runAllManagedModulesForAllRequests="true">
<remove name="RadUploadModule" />
<remove name="RadCompression" />
<add name="RadUploadModule" type="Telerik.Web.UI.RadUploadHttpModule" preCondition="integratedMode" />
<add name="RadCompression" type="Telerik.Web.UI.RadCompression" preCondition="integratedMode" />
</modules>
After I commented them, the code started to work ok.
But this proved to not be the ideal solution, so please read on...
Updated solution
After more tests with the application, I realized that RadCompression, while not absolutely required, is very useful to web applications with Telerik Ajax, because it provides transparent, on the fly compression for all ajax traffic (plus viewstate, is configured).
Because I disabled it, the application started to be slower.
So I had to find a way to re-enable RadCompression, but disable it for certain requests (like webapi endpoint for files download).
And the solution is:
Add special config section for RadCompression configuration
<configSections>
<sectionGroup name="telerik.web.ui">
<section name="radCompression" type="Telerik.Web.UI.RadCompressionConfigurationSection, Telerik.Web.UI, PublicKeyToken=121fae78165ba3d4" allowDefinition="MachineToApplication" requirePermission="false"/>
</sectionGroup>
....
</configSections>
Add handlers in system.web\httpModules
<system.web>
....
<httpModules>
<add name="RadCompression" type="Telerik.Web.UI.RadCompression" />
</httpModules>
Add handlers in system.webServer\modules
<system.webServer>
<modules runAllManagedModulesForAllRequests="false">
<add name="RadCompression" type="Telerik.Web.UI.RadCompression" preCondition="managedHandler" />
</modules>
</system.webServer>
And the critical part, to disable RadCompression for specific requests (URIs), add a new config section as below
<telerik.web.ui>
<radCompression enablePostbackCompression="true">
<excludeHandlers>
<!--This will match every api/permitfiles/download file regardless of its location in the web site--> <add handlerPath="api/permitfiles/download" matchExact="false"/>
</excludeHandlers>
</radCompression>
</telerik.web.ui>
With those changes, RadCompression is empowered globally in the app for all requests, but restricted for specific requests (like webapi files download)

MVC 5.1 debug enabled doesn't disable Bundling and minification

Running in debug from VS 2013.2RTM Pro, MVC 5.1 app.
If the compilation mode is set to debug="true" it is supposed to disable Bundling and minification but it does not. When I examine the View source on a page the styles and scripts are bundled.
<script src="/bundles/modernizr?v=K-FFpFNtIXjnmlQamnX3qHX_A5r984M2xbAgcuEm38iv41"></script>
If I set BundleTable.EnableOptimizations = false; in the BundleConfig.cs it does disable Bundling and minification but that is not how it is supposed to work. I shouldn't have to remember to toggle the EnableOptimizations setting!
Things are working properly in VS 2012 MVC 4 apps.
Is this a MVC 5.1 bug? Has anyone else had this problem? Is there a way to get debug to disable the Bundling and minification?
web.config:
<system.web>
<authentication mode="None" />
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" useFullyQualifiedRedirectUrl="true" maxRequestLength="100000" enableVersionHeader="false" />
<sessionState cookieName="My_SessionId" />
<httpModules>
<add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" />
<add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" />
<add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah" />
</httpModules>
</system.web>
_Layout.cshtml:
In header
#Styles.Render("~/Content/css") #Styles.Render("~/Content/themes/base/css")
#Scripts.Render("~/bundles/modernizr")
At end of body
#Scripts.Render("~/bundles/jquery") #Scripts.Render("~/bundles/jqueryui") #Scripts.Render("~/bundles/jqueryval")
You may have a look at this article
http://codemares.blogspot.com.eg/2012/03/disable-minification-with-mvc-4-bundles.html
or you can use this simple implementation
public class NoMinifyTransform : JsMinify
{
public override void Process(BundleContext context, BundleResponse response)
{
context.EnableOptimizations = false;
var enableInstrumentation = context.EnableInstrumentation;
context.EnableInstrumentation = true;
base.Process(context, response);
context.EnableInstrumentation = enableInstrumentation;
}
}
and then when defining your script bundles in (App_Start) you can use the base Bundle class like this
IBundleTransform jsTransformer;
#if DEBUG
BundleTable.EnableOptimizations = false;
jsTransformer = new NoMinifyTransform();
#else
jstransformer = new JsMinify();
#endif
bundles.Add(new Bundle("~/TestBundle/alljs", jsTransformer)
.Include("~/Scripts/a.js")
.Include("~/Scripts/b.js")
.Include("~/Scripts/c.js"));
I'm seeing this as well in the release version. To get around it, I'm using conditional flags to achieve the same effect.
BundleTable.EnableOptimizations = true;
#if DEBUG
BundleTable.EnableOptimizations = false;
#endif

System.Data.Objects.DataClasses.EntityCollection does not contain a definition for 'Single'

Some background info, I'm using MVC3 w/ EF & db first method, along with Razor templating. I'm passing in a view model to a view, that view model has a couple different collections of obj, i'm using one of them to populate a webgrid (wgSettings) as its source parameter. Below is the code in which i'm trying to get some detailed information about a related row.
Details:
MyInfo is the Dictionary from the viewmodel,
item is the anonymous row object that the webgrid uses to populate the row
item.Value.Value is the value of the id field of the object from the dictionary that I want to grab
MySettings is a System.Data.Objects.DataClasses.EntityCollection, therefore, I can use extension methods like Single(), FirstOrDefault(), etc.
using quick watch I am able to navigate the object and see the values I would expect, however when debugging, and accessing the view # runtime, I am getting the following error.
On line:
"#Model.MyInfo[Guid.Parse(item.Value.Value)].MySettings.Single().Value"
debugger is saying
'System.Data.Objects.DataClasses.EntityCollection' does not contain a definition for 'Single' but when I quickwatch it i am getting value.
Below is the code.
wgSettings.Column(header: "Value", columnName:"Value", canSort:true, format:
#<text>
#if (item.Value.Type == "Guid" && item.Value.Value != null) {
#Model.MyInfo[Guid.Parse(item.Value.Value)].MySettings.Single().Value
}
else if (item.Value.Type == "Boolean") {
#item.Value.Value
}
else {
#item.Value.Value
}
</text>
The Linq extension methods are not in scope, you need to add this to the top (or you can add to web.config)
#using System.Linq;
Or in the web.config in the views folder:
<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="System.Linq" />
</namespaces>
</pages>
</system.web.webPages.razor>
See this question for a similar problem for a different namespace:
Using System.Data.Linq in a Razor view

Resources