Tag Archives: ASP.NET

The file is there, but returns with 404

I am trying to load an ASPX URL, but it fails. Well, it loads when I try from IIS Express with the source code, but after I publish it to IIS, it fails with 404.

The file is right there where it should be, it just cannot be downloaded. I turn on Failed Request Tracing, hopefully it will show something. It does: 388 log entries for a single HTTP request. Fortunately the Request Summary view highlights the only warning:

MODULE_SET_RESPONSE_ERROR_STATUS

ModuleName: ManagedPipelineHandler

Notification: EXECUTE_REQUEST_HANDLER

HttpStatus: 404

HttpReason: Not Found

HttpSubStatus: 0

ErrorCode: The operation completed successfully. (0x0)

Not a big help, but it shows which module is guilty. Little joy. I look up the entry in the Complete Request Trace and check the previous entries. AspNetParse and AspNetCompile entries. Hmmm, maybe something is wrong with the ASPX file? Probably not, because it runs on IIS Express, and I have it from a NuGet package.

Anyway, I check the source code. The first line looks suspicious: the @Page directive contains a CodeFile attribute. Unusual. I change it to CodeBehind. Compile, publish.

It works.

 

Technorati-címkék: ,,

JSON or not JSON: that is the question

When you write unit tests for a REST API, you probably want to test whether the given response is in the expected format. For example you want to ensure, that the response string is a valid JSON or not.

You can find a very simple tip on StackOverflow and in other blogs as well: just check whether the first character of the response is a < or { character, because JSON is about Object Notation, right? The problem with this approach is not only that it does not perform a thorough analysis, but also that its basic statement is simply not true. According to json.org, a JSON can also contain only a single value, the specification does not require it to be an object or an array at all:

json-value

So I love JSON, 123, true and false are all valid JSON strings.

Unfortunately I could not find a simple IsValidJson method, but I could come up with this solution using Newtonsoft JSON.NET library:

try
{
    JToken.Parse(input);
    return true;
}
catch (JsonReaderException)
{
    return false;
}

Is there a better solution?

 

Technorati-címkék: ,,

Compiling your MVC views without IIS errors

Visual Studio and ASP.NET by default does not compile your MVC views during build, instead the runtime processes them at run time. The consequence of this is that any error in your views may break your app only at run time.

Fortunately you can force Visual Studio to compile your MVC views as part of the build process. Just open your .csproj file and switch the value of the MvcBuildViews element from false to true:

<MvcBuildViews>true</MvcBuildViews>

This fixes the original problem, however it often introduces another issue. You may receive the following error when you try to build or publish your web application:

It is an error to use a section registered as allowDefinition=’MachineToApplication’ beyond application level.  This error can be caused by a virtual directory not being configured as an application in IIS.

I don’t know who made up this message and what was his intention to communicate. This message does not help neither to find the error, nor to fix it.

The solution – which is definitely not obvious from the previous error – is to delete the obj folder before build.

If you do not want to manually delete that folder every time, you can add that step into your build process. Thankfully MSBuild provides the BaseIntermediateOutputPath variable which points right to the obj folder, and you can combine it with the RemoveDir task to get rid of that folder. Just open the .csproj file again and add a new element to the BeforeBuild target:

<Target Name="BeforeBuild">
    <RemoveDir Directories="$(BaseIntermediateOutputPath)" />
</Target>

If you don’t like the bin folder and want to remove that as well, you can refer to it via the BaseOutputPath variable.

 

Technorati-címkék: ,,

Suppressing forms authentication redirects

One of the most terrible pain points of correctly implementing authentication is to define how to handle unauthorized requests. So for example neither unauthenticated users, nor users who are not the members of the Admins group can request the /admin URL.

Thankfully the FormsAuthenticationModule in ASP.NET provides a built-in solution to this problem. When the module is initialized, it subscribes to the EndRequest event with the OnLeave event handler, and when the HTTP status code is 401, this event handler redirects the user to the login page. This is a very convenient feature for classic requests, however it may cause serious headaches for Ajax.

When the module redirects the request, the client receives a HTTP 302 Redirect header instead of the original 401 Unauthorized error code. As defined in the standard, the XMLHttpRequest client transparently follows the redirect and downloads the content from the URI specified in the Location header, which is usually the Login.aspx page. So when the success handler of the XHR is called, it will see the HTML markup of the login page as the result of the call, and the result code will be 200 OK which indicates success. Well, how you can handle this easily?

Until .NET 4.0  you had no other option to fix this behavior than adding a custom HTTP module to the ASP.NET pipeline. But ASP.NET 4.5 introduced a new HttpResponse.SuppressFormsAuthenticationRedirect property, which you can set to true to avoid the redirect, and force the FormsAuthenticationModule to send the original 401 error code to the browser. Because this property is attached to the Response, you cannot set it globally, but instead you have to flip this switch in every handler that requires this behavior. If you want to set it for every response, then you can implement this in the Application_EndRequest handler in global.asax.

Now it is the client’s task to handle the specific error code as required, for example by displaying a login box or a warning message in JavaScript. But you already have that logic, haven’t you?

 

Technorati-címkék: ,,

How unique is your machine key?

Most cryptography related features of the ASP.NET platform relies on the machine key, therefore it is very important to assign unique machine keys to independent applications. Thankfully the default configuration looks like ensuring this both for the validation key and the decryption key:

<machineKey validationKey="AutoGenerate,IsolateApps" 
decryptionKey="AutoGenerate,IsolateApps" />

The AutoGenerate option frees you from manually setting the keys, and the IsolateApps options ensures that unique keys are generated for every application.

But not always!

ASP.NET will definitely generate a key, but it is neither the validation key, nor the decryption key, but instead a base key (let’s call it the machine key), which is then transformed into the validation key and the decryption key. The base machine key is stored in the registry in the following location:

HKCU\Software\Microsoft\ASP.NET\4.0.30319.0\AutoGenKeyV4

Note that this key sits in the HKEY_CURRENT_USER hive, so the generated machine key belongs to the user’s that runs the application profile. This means that if you have two applications in IIS which are running with the same process identity, they will use the same machine key! One more reason why you should forget the SYSTEM, LOCAL SERVICE and NETWORK SERVICE accounts, and run all your web applications with separate ApplicationPoolIdentity. This also shows that the application pool is the real app isolation boundary.

Having two applications that share the same base key is not necessary a problem, because the keys used to validate and encrypt are created with additional transformations from this key. This transformation is determined by the second modifier after AutoGenerate. If you set IsolateApps, the runtime will use the value of the HttpRuntime.AppDomainAppVirtualPath property, which is different for two applications sitting in different virtual directories on the same website, so the generated keys will be different (which is good).

On the other hand, if you have two applications in the same path but on different websites, the value of this property will be the same for both apps. For example for an app that sits in the site root, the value is “/”, so IsolateApps does not provide you the isolation you expect!

To solve this problem ASP.NET 4.5 introduced a new modifier called IsolateByAppId, which uses the HttpRuntime.AppDomainAppId property instead of the AppDomainAppVirtualPath. The value of this property is something like this:

/LM/W3SVC/3/ROOT 

The “3” in the middle is the ID of the site in my case, and “ROOT” means that the app sits in the site root.

To summarize: the default AutoGenerate,IsolateApps setting does not necessarily provides you with unique keys, but if you host your apps in their own application pools which are running with ApplicationPoolIdentity, and you use IsolateByAppId instead of IsolateApps you can be sure, that your apps will use unique autogenerated keys.

The simplest way to test these setting is to use the localtest.me domain to create two separate websites, and then create a simple webpage that uses Milan Negovan’s code to retrieve and display the autogenerated keys.

 

Technorati-címkék: ,,

Publishing a multiproject solution to Azure

One of the great features of the Windows Azure Websites is that you can directly connect the site to your source control repository. When you change your source code, it will be automatically deployed to the Azure cloud.

It is only a few clicks to set it up, just start the New –> Compute –> Web Site –> Custom create wizard:

multisite-new

Enter a URL for your website and don’t forget to check the Publish from source control checkbox:

multisite-name

This activates the second step of the wizard where you can select your preferred source control provider, for example GitHub:

multisite-where

In case of GitHub you have to authenticate yourself via OAuth, then you can select which repository and which branch you want to publish (master is the default, but you can change that to any branch name!):

multisite-repo

Within a few seconds your website will be up and running, and Azure will start deploying your application to it.

But what if you have a Visual Studio solution which contains multiple web projects or websites, which one will be deployed? The first one.

Well, that’s great for most cases, but sometimes you want to change that behavior.

If you always want to deploy the same project/site to the cloud, you can create a .deployment file in the root of your repo, in which you define which project you want to deploy:

[config]
project = MySolution/MyWebProject.csproj

But if you have multiple Azure websites, you may want to deploy different projects of your solution to them. In this case you cannot hardwire the setting into the repo, instead you have to set on the Azure management portal. Navigate to the CONFIGURE page and scroll down to the app settings section. Create a new setting with the name Project and set the repo-root relative path to the .csproj or the folder of the website as its value:

multisite-appsettings

Just save the setting and voila, next time when you change your source code only the preset project will be deployed to this website.

 

Technorati-címkék: ,,,

ASP.NET 4.0 forms authentication issues with IE11

As I mentioned earlier, solutions that rely on User-Agent sniffing may break, when a new browser or a new version of an existing browser is released. Unfortunately because ASP.NET also contains browser-specific code, the new Internet Explorer 11 may cause some problems there as well.

Lucky coincidence, that one day after my previous post Eric Lawrence published an article about IE11 and User-Agent sniffing. Some interesting facts from his article:

  • The IE team deliberately designed the UA string to cause most sniffing logic to interpret it either Gecko or WebKit and not as previous IE version.
  • During the summer the ASP.NET team published a set of patches to fix the IE11 issues in earlier .NET versions. For example KB2836939 is for .NET 4.0, and you can find more links in Eric’s article.

The issue we experienced was on an older server that was running ASP.NET 4.0. IE11 sent the forms authentication cookie to the server, but the server completely ignored it. In the web.config file the forms element didn’t contain the cookieless attribute, because the default UseDeviceProfile worked perfectly before, however now we had to set it to UseCookies to make the authentication work with IE11 as well.

The patch mentioned earlier was not installed on this server, and we have not seen similar issues on .NET 4.5.

By the way setting cookieless="UseCookies" explicitly is a good security practice.

 

Technorati-címkék: ,,,