I have completed my initial evaluation of the .NET environment. Coming from nearly 10 years developing in PHP, it was a daunting task, but I think there are other PHP developers out there trying to make the jump and might find my thoughts useful. Therefore, I decided to make this post. It also may shed a little light in some of my recent questions here on this forum.

----------

As I sat down to look over things, I knew I was in for a shock. The .NET environment is huge. Not only are there several programming languages to choose from, but a great many project types. On top of that, some have multiple frameworks that can be uesd leverage your language of choice. And that's just the tip of the iceburg. There's crystal reports, LINQ, mobile devices, and the list goes on.

An important thing to realise in my movement to .NET is that I am not an empolyee of a company, but a guy, sitting at home. A friends and myself setup a freebsd box a fears ago, and I wrote us a small community website. We did things a certain way, and we had gotten used to it. So while I investigated thing .NET-side, I always kept those thing in mind. I had to constantly ask myself which elements of our older application should we keep intact, and which we should change. I never ruled out anything, despite personal leanings, but at the same time. I tried to see if there was a way to move as much over as we could with as little change as possible. For example, our localized phrases and templates were stored in xml files. This was a medium the non-developers were comfortable editing. While I was able to duplicate much of our old application, I began seeing other ways to do things (with the help of our good friends here at sitepoint), ways that may actually work out better in the long run.

----------

The first thing I played with was the WebForms framework. Many people confused this with .NET itself. They are not the same thing. WebForms are one of many frameworks that build on the .NET infrastructure. I found WebForms extremely easy to use, although I do have a history of OOP design, from well before my PHP days. I really liked the idea behind the template file and the code file being separate, but able to respond to each other. Controls such as the repeater made things a lot easier. In my older app, I had to load a template into a string, and while looping through a recordset, set variables that would be evaluated into it, then keep a growing array of these filled templates, then finally spit stuff out, all assembled. It wasn't elegant, but it worked. Now, all I have to do is define the template once, assign a Datasoure and call DataBind. WoW.

The next element I looked at was how urls were handled. My older application Used a single point of entry file and took certain parameters, for example: index.php?cmd=CategoryEdit&id=42. From there was a pretty simple controller -> command -> view process. I wanted to see what I could do with .NET in that regard. One thing to keep in mind, is that my idea of the MVC framework added a layer that the ASP MVC framework didn't seem to have. In my old idiology, The Command only processed data, such as postback, and decided what view to render. The command would pass any models on to the view, where output is assembled. Due to how the webforms worked, I wondered if there was a good way to integrate both. I looked long enough at the ASP MVC framework to understand how it was put together, and came to the conlusion that I would be able to come to a happy medium between the two.

----------

The first thing I did was enabled routing in my "test" application. This was done with the System.Web.Routing namespace included with the Visual Studio Professional distribution. The MVC libraries weren't required for what I wanted to do. After enabling that, I added some code to my Global.asax file, in the Application_OnStart event handler to add my one route, compelete with constraints and defaults. It isn't complete of course, just enough to test with.

Code VBNET:
Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
Dim routeDefaults As RouteValueDictionary
Dim routeConstraints As RouteValueDictionary
Dim routeDefinition As Route
 
routeDefaults = New RouteValueDictionary()
routeDefaults.Add("command", "Index")
routeDefaults.Add("action", "View")
routeDefaults.Add("id", 0)
 
routeConstraints = New RouteValueDictionary()
routeConstraints.Add("command", "Index|Category")
routeConstraints.Add("action", "View|Add|Edit|Remove")
routeConstraints.Add("id", "\d+")
 
routeDefinition = New Route("{command}/{action}/{id}", routeDefaults, routeConstraints, New DefaultRouteHandler)
 
RouteTable.Routes.Add("DefaultRoute", routeDefinition)
 
End Sub
----------

Next, I created the custom RouteHandler that would be handling the requests. At first, I tried also creating custom httphandlers and run the correct one based on the request parameters. But that seemed a little overkill when the Webforms were already well blessed handlers, and I didn't want to have to reinvent templating. So I wound up with a simple mapper, that hooked requests to a physical aspx page. I used this RouteHandler to simply enforce a more readable url, moreso than control program flow. You can see the code below, and if you pay attention, you'll see where I took advantage of the context.items collection to pass the url segments on to the page.

Code VBNET:
Public Class DefaultRouteHandler : Implements IRouteHandler
Public Function GetHttpHandler(ByVal requestContext As RequestContext) As IHttpHandler Implements IRouteHandler.GetHttpHandler
Dim virtualPath As String
requestContext.HttpContext.Items("command") = requestContext.RouteData.Values("command")
requestContext.HttpContext.Items("action") = requestContext.RouteData.Values("action")
requestContext.HttpContext.Items("id") = requestContext.RouteData.Values("id")
virtualPath = New String("~/App_Pages/{command}{action}.aspx")
virtualPath = virtualPath.Replace("{command}", requestContext.RouteData.Values("command"))
virtualPath = virtualPath.Replace("{action}", requestContext.RouteData.Values("action"))
Return BuildManager.CreateInstanceFromVirtualPath(virtualPath, GetType(Page))
End Function
End Class

At this point, I created a test page in my App_Pages folder, named CategoryEdit.aspx. In it, I placed three literals, and set their values in Page_Load event handler like such:

Code VBNET:
 Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
CommandValue.Text = "Command: " + Context.Items("command")
ActionValue.Text = "Action: " + Context.Items("action")
IDValue.Text = "ID: " + Context.Items("id")
End Sub

When the page was called, using /Category/Edit/42, the correct output was displayed.

----------

Now, all this was just a test, an exercise in my getting to know my way around .NET more, and wasn't meant to "impress" or "wow" anybody. It certainly isn't rocket science. But I just wanted to share this in case anybody found it useful.

----------

Thanks!