Maarten Balliauw {blog}

ASP.NET MVC, Microsoft Azure, PHP, web development ...

NAVIGATION - SEARCH

ASP.NET MVC framework - Security

Some posts ago, I started playing with the ASP.NET MVC framework. In an example I'm creating, I'm trying to add Forms-based security.

"Classic" ASP.NET offers a nice and easy way to set security on different pages in a web application, trough Web.config. In the example I'm building, I wanted to allow access to "/Entry/Delete/" only to users with the role "Administrator". So I gave the following snip a try:

[code:c#]

<location path="/Entry/Delete">
   <system.web>
     <authorization>
       <allow roles="Administrators"/>
       <deny users="*"/>
     </authorization>
   </system.web>
</location>

[/code]

This seems to work in some occasions, but not always. Second, I think it is very confusing to define security in a different place than my route table... Since the ASP.NET MVC framework is built around "dynamically" changing URL schemes, I'm not planning to maintain my Web.config security for each change...

In an ideal world, you would specify permissions for a route at the same location as you specify the route. Since the ASP.NET MVC framework is still an early CTP, perhaps this might be added in future versions. For now, the follwing strategies can be used.

Code Access Security

Luckily, the .NET framework offers a nice feature under the name "CAS" (Code Access Security). Sounds scary? Perhaps, but it's useful in the MVC security context!

The idea behind CAS is that you specify security requirements using attributes. For example, if authentication is required in my EntryController (serving /Entry/...), I could use the following code snippet:

[code:c#]

[PrincipalPermission(SecurityAction.Demand, Authenticated=true)]
public class EntryController : Controller {
    // ...
}

[/code]

Now let's try my example from the beginning of this post. The URL "/Entry/Delete" is routed to my EntryController's Delete method. So why not decorate that method with a CAS attribute?

[code:c#]

[ControllerAction]
[PrincipalPermission(SecurityAction.Demand, Role="Administrator"]
public void Delete(int? id) {
   ...
}

[/code]

This snippet makes sure the Delete method can only be called by users in the role "Administrator"

Exception handling

Problem using the CAS approach is that you are presented an ugly error when a security requirement is not met. There are two possible alternatives for catching these Exceptions.

Alternative 1: Using Global.asax

In Global.asax, you can specify an Application_Error event handler. Within this event handler, you can catch specific types of Exceptions and route them to the right error page. The following example redirects each SecurityException to the /Login, my LoginController:

[code:c#]

protected void Application_Error(object sender, EventArgs e) {
    Exception ex = Server.GetLastError().GetBaseException();
    if (ex is SecurityException) {
        Response.Redirect("/Login");
    }
}

[/code]

Alternative 2: Use more attributes!

Fredrik Normén has posted an ExceptionHandler attribute on his blog, which allows you to specify which type of Exception should be handled by which type of view. Hope this makes it into a future ASP.NET MVC framework version too!

Alternative 3: Use in-line CAS

Another option is to use in-line CAS. For example, you can do the folluwing in your ControllerAction:

[code:c#]

try {
    PrincipalPermission permission = new PrincipalPermission(User.Identity.Name, "Administrators", true);
    permission.Demand();
} catch (SecurityException secEx) {
    // Handle the Exception here...
    // Redirect to Login page, for example.
}

[/code]

ASP.NET DataPager not paging after first PostBack?

A few posts ago, I mentioned that I am currently giving a classroom training on ASP.NET. People attending are currently working on a project I gave them, and today one of them came up to me with a strange problem...

Here's the situation: in VS 2008, a web page was created containing 2 controls: a DataList and a DataPager. This DataPager serves as the paging control for the DataList. Databinding is done in the codebehind:

[code:c#]

protected void Page_Load(object sender, EventArgs e) {
    ListView1.DataSource = NorthwindDataSource;
    ListView1.DataBind();
}

[/code]

This works perfectly! When the page is rendered in a brwoser window, data is shown in the DataList control. Now, when testing the DataPager, something strange happens: when a page number is clicked, ASP.NET will process a PostBack, rendering... the same page as before! Clicking the DataPager again is the only way to really go to a different page in the result set.

Let's have a look at the ASP.NET page lifecycle... The page Load event is actually not the best place to call the DataBind() method. PreRender is a better place to call DataBind():

[code:c#]

protected void Page_Load(object sender, EventArgs e) {
    ListView1.DataSource = NorthwindDataSource;
}

protected void Page_Render(object sender, EventArgs e) {
    ListView1.DataBind();
}

[/code]

kick it on DotNetKicks.com

Thank you, ISP!

Living in Belgium sometimes feels like living in the desert. Over the past few years, my ISP has always offered the same: a cable modem subscription with 10Mbit downstream speed, and 256Kbit upstream speed. Great! Except for that data transfer limit of 12 GB per month and the ridiculous price of 42 EUR (that is 61 US$). And no, there are few better alternatives in this center of Europe...

Good news though! My ISP has been teasing its customers with a marketing campaign, focussing on great improvements in every Internet access subscription they offer. Rumours came along on different user forums: price drops, no more data transfer limits, ... Now here's the real improvement: everything stays the same, except you get a faster upload speed (512Kbit, yes!). Data transfer limit stays... (press release)

12 GB of data transfer is filled quite fast at 10Mbps... Here's what I think, and many others too...

 
(For the record: the information on this website represents my personal opinion. My opinion may differ with other people's opinion and my employer's opinion. This website is by no means related to other people nor my employer. )

ASP.NET MVC Framework - Basic sample application

ASP.NET MVC FrameworkYou might have noticed that I'm quite enhousiast about the new ASP.NET MVC framework.

What are you talking about?

Basically, this new ASP.NET MVC framework is an alternative to standard ASP.NET webforms, with some advantages:

  • No more postbacks or viewstate, no more page lifecycle trouble: all communication is done using a REST pattern
  • Separation of concerns: no more pages containing cluttered business logic inside view logic (MVC)
  • Testable model and controller: you can now create uinit tests which communicate with your model as if a user is browsing your website

Is there a tutorial available?

For more information and a step-by-step tutorial, check Scott Guthrie's blog:

My own sample project

For an article I'm working on, I am writing a sample application using this framework. This sample application is a very basic photo album website, listing some albums and photo's. Anyone who's interested in a sample MVC application (no data entry yet!) can download it.

Current shortcomings...

There are some shortcomings in the current CTP... Current databound controls can not be used easily. There are some ways around, but using a simple <% foreach ... %> is currently the easiest way to display data on your web page. Another way around is the MVCToolkit project, which adds support for some helper methods and classes.

ASP.NET 3.5 Extensions CTP preview released

Just over the weekend, Microsoft has released the ASP.NET 3.5 Extensions CTP. This download includes several additions to ASP.NET 3.5:

  • ASP.NET AJAX Improvements contains some new AJAX features like browser history support (back-forward), improvements to the JavaScript library, ...
  • The new ASP.NET MVC framework which I blogged about last week
  • ASP.NET Dynamic Data Support contains some new features for building a data-driven application much faster.
  • ASP.NET Silverlight support
  • ADO.NET data services, also known under the name "Astoria".

I'll be doing some testing during the week, and keep you all informed.

LINQ to filesystem

The past few hours, I've been experimenting with LINQ. As a sample application, I'm trying to create a small photo album website, which shows me all images in a specific folder on my webserver.

What does LINQ have to do with that? Everyone has used a loop over all files in a folder, and I decided to try LINQ for that matter. Here's how:

[code:c#]

var rootFolder = "C:\\";
var selectedImages = from file in Directory.GetFiles(rootFolder, "*.jpg")
                             select new { Path = file,
                                          Name = new FileInfo(file).Name,
                                          CreationDate = new FileInfo(file).CreationTime,
                                          DirectoryName = new FileInfo(file).DirectoryName
                                    };

[/code]

There you go! A collection named "selectedImages", filled with anonymous class instances containg a file Path, Name, CreationDate and DirectoryName. This collection can now be bound to, for example, a GridView:

[code:c#]

this.gridView1.DataSource = selectedImages;
this.gridView1.DataBind();

[/code]

EDIT: (mental note to myself: add LINQ keywords to syntax highlighter...) - done!