Welcome to MSDN Blogs Sign in | Join | Help

Cassini had a problem with ASP.NET projects using Routing due to the directory listing feature.  Cassini would respond with the directory listing to any request for a directory, without handing over the request to ASP.NET.  As a result, requests for friendly URLs would get intercepted by Cassini and never reach ASP.NET.

 

This update (v3.5.0.1) changes the logic around – all requests go to ASP.NET first, then Cassini intercepts 404 responses and, if the request was for a directory, it responds with the directory listing.  Applications relying on friendly URLs / Routing now work better with Cassini.

 

(6/25/2009) v3.5.0.2 fixes the default document problem

 

 

I've updated Plan 9 sample.  Please download the attachment.

Changes include:

  • GET / POST page methods instead of Page_Load / Page_Post
  • Support for stand-alone .aspx pages (in the application root directory)
  • Authorization via page directive (in addition to page method attributes)
  • Removed all use of ViewData from the sample web site
  • Html Extensions for generating links and user controls. Page and Directory first level concepts instead of path (Html.HomeLink() and Html.PageLink("Home", "Index") instead of Html.PageLink("~/Home/Index"))
  • Helpers for Http Redirects (without ThreadAbortException), Validation, Security
  • Built on top of ASP.NET MVC RC

Disclaimer: Plan 9 is a sample put together as the result of experimentation.  Plan 9 is internally built on top of ASP.NET MVC, but it is not an MVC Framework by itself.

For the future I plan to add support for simple AJAX scenarios.

I've updated the VB XML Literals View Engine sample for ASP.NET MVC RC (attached).

Thanks,

Dmitry

[Latest update here

The attached sample implements simplified Web application paradigm (called “Plan 9 MVC”) based on ASP.NET MVC. It is page-centric (it hides Controllers) but it retains many of the benefits of ASP.NET MVC. The package contains a Visual Studio solution with two projects (the standard ASP.NET MVC starter template rewritten as a Plan 9 Web Site, and the library implementing Plan 9 framework), the license document, and README document.

ASP.NET MVC provides many benefits including:

  1. Separation of Concerns and the resulting testability
  2. Better control over HTML in MVC views (compared to classic Web Forms). Rendering using HTML helpers provided for MVC View Pages.
  3. Nice looking logical URLs
  4. Productivity features like binding of HTML form fields to action method arguments and declarative authorization rules (by decorating action methods)

Plan 9 completely ignores #1 above, as it does not have Controllers visible to the user. However, the other benefits stay.

The website does not have “Controllers” and “Views” folders – it has “Pages” folder instead, containing ASP.NET pages implemented as MVC View Pages, with HTML helpers. Requests are mapped to these pages using a simple rule: ~/Home/Index is routed to ~/Pages/Home/Index.aspx

The code normally found in Action Methods of a Controller, in Plan 9 applications resides in page methods, Page_Load and the newly introduced (in Plan 9) Page_Post.

Page_Load can be decorated with [Authorize] attribute, similar to how the attribute is used on Action Methods in Controllers:

    [Authorize]
    public void Page_Load() {
        ViewData["Title"] = "Change Password";
    }
    …

Page_Post method is only executed on HTTP POST requests and its arguments are automatically bound to the request data just as Action Method arguments are:

    public void Page_Load() {
        ViewData["Title"] = "Login";
    }
    
    public void Page_Post(string username, string password, bool rememberMe, string returnUrl) {
        …
    }

Plan 9 also introduces several helper methods for link generation and validation, to simplify the page code.

Internally Plan 9 implementation is based on ASP.NET MVC. The requests are routed to one controller (all to one Action Method) that dispatches them to the corresponding pages:

    public class Plan9Controller : Controller {
        public ActionResult Action() {
            string virtualPath = Plan9.GetPath(ControllerContext.RouteData);

            if (!HostingEnvironment.VirtualPathProvider.FileExists(virtualPath)) {
                throw new HttpException(404, string.Empty);
            }

            Plan9.CurrentControllerContext = ControllerContext;
            return View(new WebFormView(virtualPath));
        }
    }

Obviously, Plan 9 is not a true MVC framework and should not be considered as such. But it does provide a simple alternative way to develop web applications preserving many of the benefits of ASP.NET MVC. In the future it would be interesting to explore a hybrid model, applications that combine true MVC with Plan 9 sub-sections.

The name "Plan 9" refers to Plan 9 from Outer Space (a 1950s zero-budget Sci-Fi movie, some claim it to be the worst movie ever made -- it's so bad it's fun to watch).

[Update for ASP.NET MVC RC available

The code in the attached ZIP file implements a custom View Engine for ASP.NET MVC Beta using VB.NET XML literals.  Instead of traditional ASP.NET pages, the views are implemented as VB.NET classes.

The package contains a Visual Studio solution with two projects (the standard  ASP.NET MVC starter template rewritten to use VB.NET XML views, and the library implementing the view engine), the license document, and README document.

Notes:

View engine registration is done in GLOBAL.ASAX in Application_Start method:

    ViewEngines.Engines.Add(New VbViewEngine)

VbViewEngine, instead of searching directories for files, looks for a class derived from VbView named ActionName in namespace *.Views.ControllerName in the assembly of the controller.

ASPX, MASTER and ASCX files implementing MVC views are replaced with VB classes derived from  VbView.  Many ASP.NET concepts have direct analogs in VB.NET (or OO world in general). For example, a master page get replaced with a base class. Here is how Index view looks in VB.NET:

    Namespace Views.Home
        Public Class Index
            Inherits SiteMaster

            Public Overrides Function RenderContent() As XElement
                Return <div>
                         <h2><%= Xhtml.Encode(ViewData("Message")) %></h2>
                         <p>To learn more about ASP.NET MVC ...</p>
                       </div>
            End Function
        End Class
    End Namespace

The entire application is compiled into one assembly.  There are no ASPX files that need to be deployed.

Unfortunately HTML helpers that come with ASP.NET MVC are not usable from VB.NET XML views because HTML helpers return strings.  XHTML helper class has been added that has [some of] the methods found on HTML helper -- they return XElements  instead of strings.  Here is the implementation of validation summary helper using VB.NET XML literals:

    Public Function ValidationSummary() As XElement
        If _viewData.ModelState.IsValid Then
            Return Nothing
        End If

        Return <ul class="validation-summary-errors">
                   <%= From e In _viewData.ModelState From m In e.Value.Errors Select _
                       <li><%= m.ErrorMessage %></li> _
                   %>
               </ul>
    End Function

The controller code in the starter template did not change at all, even though all the views have been replaced to use a different view engine.  This is a good thing -- it validates the separation of concerns in MVC.

Your feedback and suggestions are most welcome!

Thanks,

Dmitry

The attachment contains Cassini version for .NET Framework 3.5.

Highlights:

  • Runs as a single EXE -- does not require an assembly in GAC
  • Supported IPv6-only configurations
  • Upgraded to support .NET Framework 3.5
  • Includes VS project file
  • License changed to Ms-PL
Silverlight 2 beta 2 is out, so I updated Dynamic Client Script sample accordingly (attached to this post).

Last year I've published a simple ASP.NET control, called ‘Dynamic Client Script', that enables IronPython client scripting in ASP.NET pages in Silverlight 1.1 Alpha.  Since then Silverlight evolved quite a bit and Silverlight 2 Beta 1 has been released.  According to the new model, Silverlight applications are published as XAP archives containing the application code, so I've updated the Dynamic Client Script sample to work with the new model.

The user model for Dynamic Client Script stays the same -- all user needs to is to drop the control onto an ASP.NET page:
<asp:DynamicClientScript runat="server" ID="MyScript" Source="myscript.py" />
The control does all the magic, including generation of Silverlight object tag with the link to the Silverlight application (XAP archive) pointing back to the page as a request with a special path-info.  That request gets intercepted by the control, and it creates the XAP archive on the fly, and caches it across requests with the right cache dependencies so it only gets re-created when the page or the script changes.

The XAP creation code comes from Chiron, a development web server that we ship with Dynamic Languages SDK for Silverlight.  Chiron automatically creates XAP archives from any directory, to facilitate development of Silverlight application in dynamic languages.  Dynamic Client Script control does not require Chiron, it works with any ASP.NET web server, including IIS (and Cassini as well).

The updated sample:

  • Allows script inline in the ASP.NET page or in a separate file
  • Supports IronPython, IronRuby, Managed JScript
  • Supports multiple instances of Dynamic Client Script control on the same ASP.NET page
  • Includes all DLR assemblies and compliers
  • Includes sample pages

The attached package includes all the sources, binaries, and samples.

Thanks to Piyush, the second version of ASP.NET RSS Toolkit is now available on CodePlexPlease check it out.

Thanks,

Dmitry

Attached is an updated Photo Album sample. The idea is to maximize the simplicity of use - just drop default.aspx page into the [root] directory where the pictures are and it does everything for you -- list view per folder, details view for each picture, thumbnails generation and caching, etc.

It is similar to the one I've published before, but this one is implemented as a page (.aspx, not .ashx) and it handles both page views and image requests.  It is as easily customizable as any ASP.NET page -- it relies on MultiView control to switch between list and detail views.  The package includes sources in C#, IronPython, and Managed JScript -- for the latter two please install ASP.NET Futures package.

Thanks,

Dmitry

Please check out ASP.NET Futures release with Dynamic Langauges support and Dynamic Data Controls.  The former is the updated version of IronPython for ASP.NET, now based on DLR.

Thanks,

Dmitry

Attached to this post is the Dynamic Client Script sample -- an ASP.NET control that simplifies creation of AJAX-like Web pages in managed scripting languages using Microsoft Silverlight cross-browser / cross-platform technologies.

The recent release of Microsoft Silverlight enables a set of scenarios that some people might find interesting. Silverlight 1.1 Alpha release includes features that enable AJAX-like scenarios using managed dynamic languages on the client:

  • APIs to access HTML DOM from managed code
  • APIs to make HTTP requests to Web services from managed code
  • Dynamic Language Runtime (DLR) with the implementation of IronPython and Managed JScript (with more dynamic languages, including IronRuby, coming in the future).  (Please also see Dynamic Silverlight Samples on CodePlex)

As a result, it is possible to author an HTML page with IronPython client script using the following steps:

  1. Start with an HTML page
  2. Write the IronPython client script file
  3. Author a [bootstrapping] XAML file with a reference to the IronPython client script file (and add the XAML file to the project)
  4. Add a link in the HTML page to the Silverlight bootstrapping jscript files (and add the files to the project)
  5. Add jscript code to the HTML page to instantiate the Silverlight control

Dynamic Client Script control dramatically simplifies this:

  1. Start with an ASP.NET page
  2. Write the IronPython client script file
  3. Place Dynamic Client Script control onto the ASP.NET page and set 'Source' property to point to the IronPython file

Notes:

  • Dynamic Client Script control automatically renders the links to the bootstrapping jscript and to XAML (the actual links point back to the containing page and the control intercepts these requests and serves the corresponding content)
  • No additional files need to be added to the project 
  • Several Dynamic Client Script controls can co-exist in the same ASP.NET page 
  • Dynamic Client Script control (in addition to 'Source' reference) supports inline script (it uses the same link-back trick to generate the link from XAML to script)

The attached package (DynamicClientScript.zip) contains sources (licensed under Ms-PL) and samples (as a run-able Web app).

Please check this out, if you are interested.

Some time ago I wrote a simple ASP.NET in-process executor for internal testing and I am happy to see it go public on CodePlex (under name "Plasma") including NUnit integration, thanks to Steve Smith from AspAlliance.  Please check it out.

Thanks,

Dmitry

Thanks to Scott Cate the Disk Output Cache project is now on CodePlex.

Please check it out and consider contributing.

Thanks,

Dmitry

Here is a sample code that returns the current trust level, assuming this code (or the calling code up the stack), is not loaded from GAC:

AspNetHostingPermissionLevel GetCurrentTrustLevel() {
    foreach (AspNetHostingPermissionLevel trustLevel in
            new AspNetHostingPermissionLevel [] {
                AspNetHostingPermissionLevel.Unrestricted,
                AspNetHostingPermissionLevel.High,
                AspNetHostingPermissionLevel.Medium,
                AspNetHostingPermissionLevel.Low,
                AspNetHostingPermissionLevel.Minimal 
            } ) {
        try {
            new AspNetHostingPermission(trustLevel).Demand();
        }
        catch (System.Security.SecurityException ) {
            continue;
        }
 
        return trustLevel;
     }

     return AspNetHostingPermissionLevel.None;
}

The result can be cached in a static field for the duration of the app domain lifetime.

More Posts Next page »
 
Page view tracker