Thoughts from Dan Miser RSS 2.0
# Saturday, 23 November 2013
Azure has been churning out features faster than anything I can ever remember coming out of Microsoft. I finally moved to Azure with my production apps this weekend. It was a pretty painless move, as far as data center moves go. One of the biggest road blocks that I hit was trying to create virtual applications for each of my apps inside one Azure Web Site. I wanted to go this way to get the benefits of having one DNS entry, coupled with an SSL certificate, and eventually wildcard subdomains. It seemed the smart way to go, given that each app is isolated and I've been running that way on my own IIS server for a couple years (or more) now.

The key to getting things right is to select your Azure Web Site in the portal, and go to Configure. Then, at the bottom of the page you can add your virtual applications. The placeholder text says "PHYSICAL PATH RELATIVE TO SITE ROOT". Don't listen to that. Instead, make your virtual applications live underneath site\wwwroot.


If you do that, you can then download the Publish Profile Settings from your dashboard and update the <DeployIisAppPath> element to look like this: 
<DeployIisAppPath>MySite/app1</DeployIisAppPath>
Now when you deploy, the files will land on the server in the right directory. 


I couldn't find a way to get the deploy to put the files in the site\app1 directory on the server. DeployIisAppPath and RemoteSitePhysicalPath could not get me up to that level in this setup. If you know of a better way, I'd love to hear about it!

Bonus: If you're a command line junkie like me, you'll want to read how to publish an Azure site from the command line.
Saturday, 23 November 2013 23:40:46 (GMT Standard Time, UTC+00:00)  #    Comments [1] -
.NET | ASP.NET | ASP.NET MVC
# Thursday, 08 November 2012
The new DisplayMode engine in ASP.NET MVC 4 is rather nice. By default, it will detect whether you come in from a mobile device or a desktop machine, and load up a specialized view for you based on that detection.

For example, if you were trying to navigate to http://www.example.com/Players from an iPhone, the default behavior will be to look for Players\Index.Mobile.cshtml, followed by Players\Index.cshtml. Whichever it finds first will be the view that gets used. Note that this also requires you to have a _Layout.Mobile.cshtml file.

This is great for new projects, but I have a non-trivial app with a lot of views that have been built over the years using the technique by Scott Hanselman. That approach would look for the file in Players\Mobile\Index.cshtml. I was not looking forward to renaming all of those files.

In order to use my already existing file structure, I added one class:


public class SubfolderDisplayMode : DefaultDisplayMode
{
    public SubfolderDisplayMode() : base("Mobile")
    {
        // Be sure to use 51degrees.mobi, or a good browser capabilities file
        ContextCondition = (context => context.GetOverriddenBrowser().IsMobileDevice);
    }

    protected override string TransformPath(string virtualPath, string suffix)
    {
        var dir = VirtualPathUtility.GetDirectory(virtualPath);
        var filename = VirtualPathUtility.GetFileName(virtualPath);
        return VirtualPathUtility.Combine(dir, "Mobile/" + filename);
    }
}

Registered it in my Globabl.asax.cs:

DisplayModeProvider.Instance.Modes.Insert(0, new SubfolderDisplayMode());

It works very well, and I can come back and rename those files later.

Also be sure to put a call to @Html.Partial("_VewSwitcher") somewhere in your desktop _Layou.cshtml file so the user can get back to the mobile version of the site.

Updated on 11/9/12 to clean the sample code up a bit
Thursday, 08 November 2012 21:11:20 (GMT Standard Time, UTC+00:00)  #    Comments [0] -
ASP.NET MVC
# Wednesday, 29 August 2012
After installing the RTM version of VS2012 last week and upgrading my project, I noticed that my web site was broken. The real culprit seemed to be that Microsoft changed how bundling works (the process of combining and minifying resources like js script and css files) between the RC version and the RTM version. For an excellent background on what this feature can do for you, see this tutorial.

It turns out my real problem was with Kendo. They don't provide non-minified files in the trial version, so the new bundling mechanism wasn't including the minified assets, which meant the Kendo minified assets were getting stripped out when I was trying to run under debug. (Reference here). I was able to use the work-around offered on this thread, and things started working again.

However, there are a few wrinkles when using the bundling code, so I thought I'd capture my experiences here. For example:

  • For 3rd party components that don't ship with non-minified assets, you need a better way around the default bundling strategy provided in the kendo article above. The solution provided in that thread of removing the min files from the ignore list will end up duplicating other assets that do provide both a minified and regular version of their assets while running in debug mode, e.g. jquery. There is a workaround for this, though: If you specify your bundle file's pattern with the {version} macro, then the bundling framework is smart enough to include just the one copy of the asset. If you use a wildcard in the pattern (as shown in the thread), you will get duplicate min and non-min versions of the asset when you render. Here is what your code should look like:
    
    bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
         "~/Scripts/jquery-{version}.js"));
    
  • When specifying a CDN location, right now, you can't use the {version} macro, so you end up with a hardcoded reference for your CDN link (1.7.1 in the sample) and a {version} macro for the non-CDN reference (which could be 1.7.1, 1.7.2, or anything else that exists in your solution). This means that when you update locally, you need to remember to keep those version numbers in sync. The CDN path could take the version you have locally and substitute it in the CDN path that you provide removing this requirement.
  • In the tutorial, there is a fallback script that they recommend you write after your Scripts.Render statement so you can gracefully fall back to the local version if the CDN version doesn't load. It would be much better if that fallback code would be emitted for you when you call Scripts.Render.
  • Speaking of CDN, it appears that there is a very tight coupling assumed between a bundle and a CDN path. In other words, you cannot include multiple assets in one bundle because the CDN path for the bundle assumes it is a reference to a specific file on the CDN. It would be better to have CDN paths be tied to each individual item in the bundle.
  • Also relating to CDN support: The CDN path will only be used if you set bundles.UseCDN to true AND you either have BundleTables.EnableOptimization set to true or compilation debug set to false in your web.config. Granted, you probably only want to use the CDN when you are pushing to production, but while trying to test things out, I was doing it locally and this caught me by surprise. The 2 items should be independent of each other. If not, why even bother having the UseCDN property?

It seems that there is quite a bit of friction in the current version of the bundling framework. Fortunately, it resides in the Optimization assembly which can be upgraded independently of the entire MVC framework. I hope Microsoft releases an update very soon to overcome these obstacles. I have every reason to believe that they will since I'm seeing the author of this assembly answering tons of questions on StackOverflow.

Wednesday, 29 August 2012 19:39:05 (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
ASP.NET MVC
# Monday, 30 July 2012
I'm trying to settle on a standard for a grid component for use in an ASP.NET MVC app. It looks like datatables.net is the winner for now.

Here is my quick run-down on how to get it working:

  • Using NuGet, install Mvc.Jquery.Datatables
  • Using NuGet, install EmbeddedVirtualPathProvider.
  • In the generated App_Code\RegisterVirtualPathProvide.cs file, add the following line where the comment tells you to. These last 2 steps are needed to get the grid to show up on the page.
    
    {typeof(Mvc.JQuery.Datatables.DataTableVm).Assembly, @"..\Mvc.JQuery.Datatables"} 
    
  • The sample found here is a little outdated and the instructions on the page don't match what's happening inside the actual view. Use these instructions instead:
    • In the controller, you need to return a DataTablesResult (not an IDataTablesResult). The assembly relies on finding an action with this return type, so that also means that you can't redirect views, which isn't the worst thing since this should be an AJAX request anyways.
    • In the view, add this to the top (instead of the calls to the link and script tags cited in the page:
      
      @Html.DataTableIncludes(jqueryUi:false)
      
    • In the view, the code should look similar to this where you want the grid (remember, you need to have the controller action method return DataTablesResult in order for this to work):
      
      @{
        var vm = Html.DataTableVm("table-id", (DashboardController h) => h.GetWireHistoryData(null));
      }
      @Html.Partial("DataTable", vm)
      

There is a good series expanding on datatables usag in ASP.NET MVC over at codeproject.com.

Thanks to Harry for the NuGet package. It definitely will make keeping things up to date much easier.

Monday, 30 July 2012 20:46:19 (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
ASP.NET MVC
# Sunday, 19 February 2012
I have an HTML form that allows users to fill out a bunch of different parameters, and then it will display the result on the same page via an AJAX call. Pretty standard, and it works great. I had a request to allow for exporting the data in Excel format. Unfortunately, just returning a File ActionResult won't work from within the context of an Ajax form. There were some workaround posted out there (e.g. hidden iframe, duplicate the form on the page, etc.). I found the following approach to be a nice compromise and DRYs things up considerably. The key is that by putting the onclick on the Export button to do this.form.submit(), it forces the request to be a standard POST and not an AJAX call.

View.cshtml


@using(Ajax.BeginForm("ReportData", new AjaxOptions {UpdateTargetId="result"})) {
  ... other input elements here
  <input type="submit" value="Display" />
  <input type="submit" value="Export" onclick="this.form.submit();">
}

Controller.cs


public ActionResult ReportData(... parameters go here ...) {
  if (Request.IsAjaxRequest()) {
    // Do the normal behavior here to build up a string
    return Content(s);
  }

  // I actually stream the result with a custom ExcelResult action, 
  // but this shows how to just return a file.
  return File(@"c:\library\report.xls", "application/vnd.ms-excel");
}
Sunday, 19 February 2012 17:33:35 (GMT Standard Time, UTC+00:00)  #    Comments [0] -
ASP.NET MVC
# Sunday, 15 January 2012
What's the difference between these 2 methods?

Html.ActionLink(string linkText, string actionName, object routeValues, object htmlAttributes)
Html.ActionLink(string linkText, string actionName, RouteValueDictionary routeValues, IDictionary htmlAttributes)

Yes, they have the same number of parameters. Yes, they even have the same parameter names. So in essence the intent of calling either of these methods is to build up a link with the passed in route values and HTML attributes. Yet the difference between these 2 methods couldn't be more pronounced.

Take this line of code:


@Html.ActionLink("Back to List", "Index", TempData["SavedRouteValues"], null)
What I wanted was an easy way to retain the settings of a Telerik ASP.NET MVC Grid and build up a link to bring me back to the correct state. This line of code does that. However, it generates a link similar to this (word-wrapped here for clarity):

http://www.foo.com/Grid?Count=3&Keys=System.Collections.Generic.Dictionary%602%2BKeyCollection%5BSystem.String%2CSystem.Object
%5D&Values=System.Collections.Generic.Dictionary%602%2BValueCollection%5BSystem.String%2CSystem.Object%5D

Brutal. Ugly.

To fix this, just use this code (a simple typecast) to force the correct overloaded method to be picked:


@Html.ActionLink("Back to List", "Index", (RouteValueDictionary)TempData["SavedRouteValues"], null)

The moral of the story? If you're an API desiger, don't make overloaded methods lightly. Make sure they add value and distinction. A strong type vs. an object reference doesn't pass that test. If you do violate that rule, however, then at least be sure that the overload fulfills the intent and implied contract of that method.

Sunday, 15 January 2012 15:52:59 (GMT Standard Time, UTC+00:00)  #    Comments [0] -
ASP.NET MVC
# Saturday, 15 October 2011
I've had a web application written using iUI for a couple of years now. It's been stable and rock solid, and I really appreciate the leg up that it gave me. However, this weekend I converted away from iUI to jQueryMobile. I have another application in production already using jQueryMobile, and it is absolutely an amazing library.

The reasons I went with this move were:
  • iOS 5 had substantial changes to Safari and my existing application is broken in many places. Instead of spending time debugging and fixing something 2 years old, I figured I'd take the time to port to jQueryMobile.
  • I've had to leave iUI at version 0.31 for this entire 2 year period. When they started development on the 0.4 version, they changed form submissions to break if you had multiple form fields with the same name. I absolutely had to have this capability in order to support ASP.NET MVC list binding. I reported the issue in the forums, and it didn't get much attention. Sure, it's open source, but if I have to chase down bug fixing in a framework I'm not intimately familiar with, it's a negative.
  • There is no easy way with the released version of iUI to do things like jQuery calls, hook events into the page create/show and hide/destroy. Sure, there are code modifications you can find on the web, but it's a forking nightmare and tough to maintain (is this for 0.31, 0.4, or 0.5? does it require other extensions or modifications? etc.).
  • From a non-technical perspective, the roadmap of iUI has been all over the place. I can't remember for sure, but I think it was originally slated for moving 0.4 in to release status in like June of 2009. It's been pushed out over and over again, trimmed in scope, and there just doesn't seem to be traction or consensus to move the product forward. In contrast, jQueryMobile is looking to have a 1.0 release in the next few weeks with constant releases over the past few months.

Saturday, 15 October 2011 22:26:06 (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET | ASP.NET MVC | iPhone
# Thursday, 01 September 2011
While creating a view model for an MVC 3 application, I annotated a property with the DataType.EmailAddress attribute. My thinking was that it would validate whether or not the contents of the property was in a valid email format. The attribute does not perform validation, however. This StackOverflow article discusses some ways to add that functionality.

Thursday, 01 September 2011 03:31:51 (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET | ASP.NET MVC
# Sunday, 17 July 2011
I've been ussing CC.NET for probably the last 5 years with good success. At work, we recently migrated to TFS 2010 (installation and configuration are brutal, but it's sort of nice when it all works). I figured I'd take this time to look around and see what I've been missing on the continuous integration scene for my personal projects. The 2 leading contenders were TeamCity and Bamboo. I went with TeamCity since I use ReSharper, and think the JetBrains guys are pretty top-notch.

Installation was drop-dead simple. Configuring was pretty straight-forward, but I had an assist from StackOverflow, which led me to this amazing article/series by Troy Hunt. After following Troy's instructions, and slightly adjusting for the obvious version differences, I had things up and running, with a completed build inside 15 minutes.

I also configured the Build Triggering step because I want the build to fire off each time I checkin. I've got a few things to take care of (notifications of broken builds, code coverage, etc.), but it looks like this is a much easier application to configure than CC.NET.

Sunday, 17 July 2011 02:36:26 (GMT Daylight Time, UTC+01:00)  #    Comments [1] -
.NET | ALT.NET | ASP.NET MVC
# Wednesday, 25 May 2011

I needed to allow a user the ability to select multiple items in a list and select them. A simple multiselect listbox was not going to suffice, given the number of items in the list. I started searching to see what was out there as a jQuery plugin or control. The search was pretty frustrating. There were a couple out there that have apparently been abandoned, and several that just didn’t meet my needs. I will say that the coolest one that I found that didn’t meet my needs was from Eric Hynds. It was really well done, but I didn’t want the combobox type metaphor with checkboxes. I wanted the lists to display with more real estate to make things more obvious.

I finally found jQuery UI Multiselect.

jquerymultiselect

The problem is, it wasn’t immediately obvious what to download. The link I just referenced says it supports jQuery 1.5 and jQuery UI 1.8. But if you go to github, things get a bit confusing. The README says the repository isn’t actively maintained anymore. Further complicating things is that the original page above points to a broken github link as the replacement. The README file on github points to the latest version, though.

The problem then becomes that the file dates on the newer branch are older than the unmaintained branch! Also troubling is that the link to the demo page on this README says it supports jQuery 1.4.2 and jQuery 1.8, which is older than the unmaintained version. You also need to be sure to download the source from the Download link on github, and not the packages. It looks like the “next” branch will work, but I’ve had to fix like 3 or 4 things in that version to get it to work the way I would expect it to. I’ll bundle those changes up and submit a pull request.

Long story short, I would recommend using this download link and get at least version 0.3-27.

Wednesday, 25 May 2011 16:55:25 (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
ASP.NET MVC
# Friday, 20 May 2011

In ASP.NET WebForms, the following code snippet will render just fine, no matter where it is in the page:


<% if (!string.IsNullOrEmpty(machine.SerialNumber)) { %>
  Response.Write("(" + machine.SerialNumber + ")";
<%}%>

However, if you just convert that over to Razor, the Response.Write call will execute before the rest of the page gets executed, resulting in the data in Response.Write to be rendered before any part of the page. The correct translation should be:


if (!string.IsNullOrEmpty(machine.SerialNumber)) {
  <text>(@machine.SerialNumber)</text>
}

If your Response.Write isn't buried in an if statement, then it's even easier, as you won't even need a <text> block due to the code/markup parsing that Razor does!

Friday, 20 May 2011 06:15:10 (GMT Daylight Time, UTC+01:00)  #    Comments [2] -
ASP.NET MVC
# Wednesday, 02 February 2011

For an ASP.NET MVC application, consider the following code fragment, where GetDetails will return HTML markup:


<%using (Ajax.BeginForm("GetDetails", new AjaxOptions { UpdateTargetId = "result" })) { %>
  <input type="submit" />
<% } %>
<span id="result" />

This code works beautifully in Firefox and Chrome, but in IE (at least 7 and 8), it ends up chewing up parts of the master page, wreaking havoc on the layout of the rendered page. The problem is that the span tag is a void element (it only has a start tag). If you physically specify the span as a start and end tag, e.g. <span id="result"></span>, then the code will work fine in all 3 browsers.

I was tempted to blame IE, and I still sort of do, but at least they're handling the HTML spec properly. w3.org clearly specifies that the span tag is not allowed to be a void element (search within the page for "void element" to see the list of allowed void elements), and it's consistent on the span reference page. The reason I still sort of blame IE is:

  1. Mozilla and Chrome understand that a void span element can be expanded in to start and end tags
  2. A void span element works just fine if it's enclosed in another HTML element, e.g. <td><span id="result" /></td> will display the returned HTML just fine
  3. When looking at the rendered page with IE Developer Tools, if a void span element is encountered in a content page, they go back to the master page and stuff the rest of the master page in the span. I guess they're free to implement malformed HTML anyway they like, but this just seems crazy.

The takeaway: All of this due to a missing end tag for a span. Ugh!

Wednesday, 02 February 2011 02:49:29 (GMT Standard Time, UTC+00:00)  #    Comments [0] -
ASP.NET | ASP.NET MVC
# Saturday, 15 January 2011
Rather than another "me too" post on the release of ASP.NET MVC 3, which Hanselman, Haack, and Guthrie have covered in-depth, I thought I'd post the good news that a couple of bugs that have bothered me are fixed in this version.

  1. There was a problem when using auto-detecting view engines when compiling under release mode. Basically, if you hit the site with your desktop browser first, and then come in with the mobile phone, you would still be presented the desktop version. This is now fixed.
  2. I posted about a problem with binding with the RC2 release. This also appears to be fixed.
Throw in the new scaffolding support, and 2011 is shaping up to be a great year for MVC.
Saturday, 15 January 2011 07:25:35 (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | ASP.NET MVC
# Monday, 03 January 2011
I recently moved away from shared hosting, and went to a virtual private server in order to scale a site out better. Unfortunately, this meant that I needed to take on more administration of the server to do things that are done for me in a shared hosting environment. One feature that I have come to rely on is one click publishing from VS.NET 2010. In order to make this work, you need to have WebDeploy set up properly.

I found the steps from this page to be very helpful. Another good guide can be found here.

Be careful if you install Web Deploy via the Web Platform Installer. For some reason, when I did this, the Management Service Delegation feature was not installed. I ended up uninstalling and then installing straight from the official site, and the feature was available.

I initially had some settings wrong, and was getting back HTTP 401 and 550 errors. The log files didn't provide much help, but you can add tracing to help diagnose the cause of most issues.

Monday, 03 January 2011 16:12:24 (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | ASP.NET MVC
# Monday, 13 December 2010
I updated my web sites to ASP.NET MVC 3 RC2, and started receiving exceptions when model binding. If you want the short version, visit this forum post for the answer. While my errors weren't caused by the same issue that was originally reported in that thread, the fix does work. To sum up even further, just add this line of code in your Global.asax Application_Start method:

ModelMetadataProviders.Current = new DataAnnotationsModelMetadataProvider(); 

The longer story is that I have a pretty involved multi-step (think "wizard"), deep-level object graph built up over many pages, so I immediately feared that I was unknowingly exploiting some loophole that just got fixed for RC2. I built a test case, so in the interest of not having to build that test case up from scratch again, it looked like this:
Model


public class Foo
    {
        private List<Bar> _bars;
        private List<Baz> _bazs;

        public Foo()
        {
            _bars = new List<Bar>();
            _bazs = new List<Baz>();
        }

        public List<Bar> Bars
        {
            get { return _bars; }
            set { _bars = value; }
        }

        public List<Baz> Bazs
        {
            get { return _bazs; }
            set { _bazs = value; }
        }
    }

    public class Bar
    {
        public int Amount { get; set; }
    }

    public class Baz
    {
        public int Value { get; set; }
    }

Controller


        public ActionResult Index()
        {
            var foo = new Foo();
            foo.Bars.Add(new Bar { Amount = 4});
            foo.Bars.Add(new Bar { Amount = 23 });
            foo.Bars.Add(new Bar { Amount = 30 });
            foo.Bazs.Add(new Baz { Value = 100 });
            foo.Bazs.Add(new Baz { Value = 200 });
            TempData["foo"] = foo;
            return View(foo);
        }

        [HttpPost]
        public  ActionResult Index(IList<Bar> bars, IList<Baz> bazs)
        {
            Foo foo = (Foo) TempData["foo"];
            foo.Bars.Clear();
            foo.Bars.AddRange(bars);
            foo.Bazs.Clear();
            foo.Bazs.AddRange(bazs);
            TempData["foo"] = foo;
            return RedirectToAction("Summary");
        }

        public ActionResult Summary()
        {
            Foo foo = (Foo)TempData["foo"];
            return View(foo);
        }

View


<% using(Html.BeginForm()) { %>
<%
    int barid = 0;
    foreach (var item in Model.Bars){%>

<%= Html.Hidden("Bars.index", barid) %> Bar:<%= Html.TextBox("Bars[" + barid +"].Amount", item.Amount) %> <% barid++; }%> <% int bazid = 0; foreach (var item in Model.Bazs) {%> <br /> <%=Html.Hidden("Bazs.index", bazid)%> Baz: <%=Html.TextBox("Bazs[" + bazid + "].Value", item.Value)%> <% bazid++; }%> <p /> <input type="submit" value="Next" /> <% } %>

I would receive the following call stack when trying to submit the form:


The parameters dictionary contains an invalid entry for parameter 'bazs' for method 
'System.Web.Mvc.ActionResult Index(System.Collections.Generic.IList`1[MvcApplicationRC2.Models.Bar], System.Collections.Generic.IList`1[MvcApplicationRC2.Models.Baz])'
in 'MvcApplicationRC2.Controllers.HomeController'. The dictionary contains a value of type 'System.Collections.Generic.List`1[MvcApplicationRC2.Models.Bar]', 
but the parameter requires a value of type 'System.Collections.Generic.IList`1[MvcApplicationRC2.Models.Baz]'.
Parameter name: parameters
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and
where it originated in the code.

Exception Details: System.ArgumentException: The parameters dictionary contains an invalid entry for parameter 'bazs' for method 
'System.Web.Mvc.ActionResult Index(System.Collections.Generic.IList`1[MvcApplicationRC2.Models.Bar], System.Collections.Generic.IList`1[MvcApplicationRC2.Models.Baz])'
in 'MvcApplicationRC2.Controllers.HomeController'. The dictionary contains a value of type 'System.Collections.Generic.List`1[MvcApplicationRC2.Models.Bar]', 
but the parameter requires a value of type 'System.Collections.Generic.IList`1[MvcApplicationRC2.Models.Baz]'.
Parameter name: parameters

Source Error:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be 
identified using the exception stack trace below.

Stack Trace:

[ArgumentException: The parameters dictionary contains an invalid entry for parameter 'bazs' for method 'System.Web.Mvc.ActionResult
Index(System.Collections.Generic.IList`1[MvcApplicationRC2.Models.Bar], System.Collections.Generic.IList`1[MvcApplicationRC2.Models.Baz])' in
'MvcApplicationRC2.Controllers.HomeController'. The dictionary contains a value of type 'System.Collections.Generic.List`1[MvcApplicationRC2.Models.Bar]', 
but the parameter requires a value of type 'System.Collections.Generic.IList`1[MvcApplicationRC2.Models.Baz]'.

Parameter name: parameters]
   System.Web.Mvc.ActionDescriptor.ExtractParameterFromDictionary(ParameterInfo parameterInfo, IDictionary`2 parameters, MethodInfo methodInfo) +484514
   System.Web.Mvc.<>c__DisplayClass1.<Execute>b__0(ParameterInfo parameterInfo) +18

   System.Linq.WhereSelectArrayIterator`2.MoveNext() +85
   System.Linq.Buffer`1..ctor(IEnumerable`1 source) +325
   System.Linq.Enumerable.ToArray(IEnumerable`1 source) +78
   System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters) +133

   System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +27
   System.Web.Mvc.<>c__DisplayClass15.<InvokeActionMethodWithFilters>b__12() +55

   System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation) +263
   System.Web.Mvc.<>c__DisplayClass17.<InvokeActionMethodWithFilters>b__14() +19

   System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +191
   System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +343

   System.Web.Mvc.Controller.ExecuteCore() +116
   System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) +97
   System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext) +10

   System.Web.Mvc.<>c__DisplayClassb.<BeginProcessRequest>b__5() +37
   System.Web.Mvc.Async.<>c__DisplayClass1.<MakeVoidDelegate>b__0() +21
   System.Web.Mvc.Async.<>c__DisplayClass8`1.<BeginSynchronous>b__7(IAsyncResult _) +12

   System.Web.Mvc.Async.WrappedAsyncResult`1.End() +62
   System.Web.Mvc.<>c__DisplayClasse.<EndProcessRequest>b__d() +50
   System.Web.Mvc.SecurityUtil.<GetCallInAppTrustThunk>b__0(Action f) +7

   System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Action action) +22
   System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +60
   System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +9

   System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +8841105
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +184
Monday, 13 December 2010 02:29:59 (GMT Standard Time, UTC+00:00)  #    Comments [2] -
.NET | ASP.NET MVC
# Wednesday, 10 November 2010
With the near-release of ASP.NET MVC 3, I've been looking at the new Razor view engine. It's quite nicely done and removes the constant "context switching" between code and layout.

In my web site, I used Scott Hanselman's auto-detecting view engine, and it has served me extremely well. However, with the relentless march of technology releases, a couple things should be pointed out:

  • If you want to use Razor on the mobile side, you just need to inherit his original class from RazorViewEngine instead of WebFormViewEngine. (Obviously you should probably do this in a new class, or else the original class name of MobileCapabeWebFormViewEngine will not exactly match up to what the class actually does).
  • The original Mobile Device Browser File project has disbanded. Very sad news, as this was a nice project that kept on top of new smart phones as they were released. It looks like 51 degrees has stepped up to give us an alternative. I opened up an issue to request providing this as a NuGet package. I'll definitely sign up to take this task on if it gains traction, and they want the help.
Wednesday, 10 November 2010 02:04:33 (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | ASP.NET MVC
# Wednesday, 24 February 2010
I use list binding in my ASP.NET MVC applications in several places. When it works, it is truly magnificent. When it doesn't, it's just maddening. Here's a quick heads up for those of you that use list binding in MVC. You would expect the following 2 lines to render the same HTML, but they don't. To get list binding to work, you need the HTML to read something like this (I'm just listing the attributes in question here):


<input name="Results[0].Score" />

The old TextBox helper works fine, since you're assigning the name attribute:


Html.TextBox("Results["+id+"].Score", Model.Score)

This code, however:


Html.TextBoxFor(r => r.Score, new { name = "Results[" + id + "].Score" })

produces the following output, which means the Score property won't get bound properly.


<input name="Score" />

The problem is that in the TextBoxFor code, the name attribute is ignored. To be more precise, the custom name is added, but the attribute is then replaced by the name derived from the model.

Wednesday, 24 February 2010 04:12:13 (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | ALT.NET | ASP.NET MVC
# Tuesday, 19 January 2010
I just updated my ASP.NET MVC 1.0 application to use ASP.NET MVC 2 RC. It was a pretty painless process. Be sure to follow the Release Notes on the download page, and many applications will be ready to go. Here are some extra things that might help get you unstuck:
  • If you're using the ASP.NET MVC Futures (Microsoft.Web.Mvc) assembly, be sure to download the new one that works with ASP.NET MVC 2.
  • If you're using the Telerik ASP.NET MVC components, be sure to download version BETA 2009.3.1218 or later.
  • Way, way, way back in the ASP.NET MVC 1.0 beta days, they had a very nice mechanism to update lists of items by tying UI fields to index numbers, so you could use primary key identifiers to help keep track of what fields were modified where. In the 1.0 RC release, Microsoft changed how it worked to do things sequentially instead. I was using the IndexModelBinder found in that thread with great success ever since then. However, Microsoft added back in the index support to ASP.NET MVC 2 RC. This means that you will have to delete the old IndexModelBinder since it won't compile anymore. Thankfully, I didn't have to change a line of my code. Nice job of code compatibility!!
Tuesday, 19 January 2010 02:52:39 (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | ASP.NET MVC
# Sunday, 08 November 2009
Telerik just released an extremely impressive library of components (Grid, Menu, TabStrip, and MenuBar), written for MVC. They are truly first-class, from the architecture, to the development experience, to the finished screens that your user sees. They released them as open-source, and even better, these controls are written from the ground up to support ASP.NET MVC.

Be sure to check out this awesome write up on how to Use the grid in a CRUD scenario. Very nicely done.

I'm not a fan of the whole "Edit/Delete" action column. I'd much rather just have a link on the column to take me to the detail screen. Here's the way I solved that:


    <% Html.Telerik().Grid(Model)
        .Name("Grid")
        .PrefixUrlParameters(false)
        .Columns(columns =>
        {
            columns.Add(o => o.CollectionDate).Template(c => { %>
                <%= Html.ActionLink(c.CollectionDate.ToShortDateString(), "View", new { Id = c.Id })%> <%
            }).Width(40);
            columns.Add(o => o.Location.Name).Width(40);
        })
        .Scrollable()
        .Sortable()
        .Pageable()
        .Filterable()
        .Render();
    %>
Sunday, 08 November 2009 03:00:21 (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | ALT.NET | ASP.NET MVC
# Friday, 06 November 2009
I've never been happier that I chose a technology after today. I have a production web application built using ASP.NET MVC, and it has been working with almost no issues for over a year now. As a matter of fact, it is the cornerstone used to run our business. I've had the default blue skin in use since day 1 (ya, ya, I know, I know. I've been so lazy, I haven't even switched out to pre-built templates), and we run the app on the iPhone. It works, but there's always pinching, zooming and scrolling going on. I finally bit the bullet after thinking to myself "Why not create a view tailored to the iPhone to enhance the experience?" one too many times. About 12 hours later, the entire application was done with an auto-detected, optimized look and feel for the iPhone. I am now convinced that I've just been paid back with the technical dividends for investing in ASP.NET MVC. :)

To help the next guy out who walks down this path, here are all of the links that I used during this process:

Friday, 06 November 2009 23:44:02 (GMT Standard Time, UTC+00:00)  #    Comments [1] -
ASP.NET | ASP.NET MVC
# Tuesday, 13 October 2009
Since my last post, the date has changed from October 9th to October 12th. The reason this is important is that the functions that needed to calculate the date based on the current date are now coming through a different code path. Before, everything worked great. As of October 10th, not so much. The fix is simple - the getDate function was missing the parentheses to make it a method call. The fix is quite simple and is listed below:

var day = (now.getDate() < 10) ? "0" + now.getDate() : now.getDate();
Tuesday, 13 October 2009 05:11:13 (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
ASP.NET | ASP.NET MVC
# Friday, 09 October 2009
I have several reports in my ASP.NET MVC application that are date-oriented. I had start date and end date text boxes, and things worked fine. What I really wanted was something that would allow those date boxes to be populated with a variety of canned date ranges (e.g. Year to Date, Last Month, etc.). I found just what I was looking for in a pure JavaScript implementation here.

The one problem I found was that "Last Month" was being calculated incorrectly. Below is the simple fix. Thanks to epalla for the original code.


// last month 
case "lastmo":
    // we need a new month variable for month-1, also formatted correctly
    var lastmonth = ((month - 1) < 10) ? "0" + (month - 1) : (month - 1);
    startbox.value = lastmonth + "/01/" + year;

    // now grab the last day of the month (30, 31? we don't know!)
    var moend = new Date(year, (month - 1), 0);
    endbox.value = lastmonth + "/" + moend.getDate() + "/" + year;

    break;
Friday, 09 October 2009 02:44:07 (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
ASP.NET | ASP.NET MVC
# Sunday, 31 May 2009
Given a set up like this (where ExpenseSummaryData returns some arbitrary HTML fragment) :

<%using (Ajax.BeginForm("ExpenseSummaryData", new AjaxOptions { UpdateTargetId = "result" })) { %>
    <label for="startDate">Start Date:</label>
    <%= Html.TextBox("startDate") %>
    <br />
    <label for="endDate">End Date:</label>
    <%= Html.TextBox("endDate")%>
    <br />
    <input type="submit"/>
    <br />
    <span id="result"/>
<% } %>

If that is all your page does, you will notice that you get taken to a new page when pressing Submit. The data on the new page is the HTML fragment returned by the AJAX call, but that's all it contains (e.g. no master page), and it's clearly not replacing the result span.

The reason for this is that I forgot to add the following lines to the <head> section in the original page:


    <script src='<%=ResolveUrl("~/Content/js/MicrosoftAjax.debug.js")%>' type="text/javascript"></script>
    <script src='<%=ResolveUrl("~/Content/js/MicrosoftMvcAjax.debug.js")%>' type="text/javascript"></script>

After adding those declarations in, the content in the span tag is properly updated and it looks like a real AJAX call.

Sunday, 31 May 2009 17:38:24 (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET | ASP.NET MVC
# Thursday, 26 February 2009

I've been playing with ways to write a solid (and even SOLID :)) architecture with ASP.NET MVC. I started with a plain LINQ to SQL approach, and then migrated to LightSpeed, and finally ended up checking out S#arp last week. Here are my notes of pros/cons on each approach. Yes, I could (and most likely will) address some concerns by writing code for it. This is more of a laundry list of the state of things as I see them at this point in time.

LINQ to SQL

Pros

  • Visual designer

Cons

  • MS is talking about phasing LINQ to SQL out and forcing people towards Entity Framework. I'm pretty sick of chasing MS's data-access strategies around every year.
  • LINQ to SQL mostly defaults you to a 1:1 mapping between your database and your model.
  • Support for modifications to the schema sucks, to be generous.
  • No UnitOfWork concept. Of course, as I prepared this blog entry, I found this article published just today, so maybe that would address this point.

LightSpeed

Pros

  • Support is outstanding.
  • Nightly builds are available.
  • Visual designer.
  • Proven patterns bundled in their core libraries (UnitOfWork, Repository, Entity, etc.).
  • Picks up changes from the schema flawlessly.

Cons

  • Commercial and propietary.
  • Lacks quite a bit of LINQ support. For example, groupby and join are not supported. This meant that I use LINQ to SQL when I need these features. Fortunately, that's all isolated to my report module, so it's not as horrible as it could be.

S#arp

Pros

  • Open Source
  • Uses standard, widely adopted open source libraries: NHibernate, Windsor, etc.
  • Convention over Configuration
  • Scaffolding

Cons

  • I'm not digging the T4 templating mechanism. They conflict with VisualSVN and Developer Express tools, and having to write a template for each and every entity is cumbersome.
  • No visual designer
  • No ability to import entities from an existing database. Yes, they like DDD, but in almost every project I've been a part of, the database is the thing that already exists.
  • No UnitOfWork pattern (I might be able to fit code out there that does this in with S#arp). The [Transaction] attribute approach feels a bit dirty.
  • The scaffolding is a bit too simple. It doesn't build up object graphs with links (for display) or SelectLists (for editing). Yes, I can add that. It probably will get that functionality at some point, too. But it doesn't do it right now.

For now, I think I'll be staying with LightSpeed, but I'll be watching S#arp very carefully.

Thursday, 26 February 2009 21:17:53 (GMT Standard Time, UTC+00:00)  #    Comments [0] -
ASP.NET MVC
# Friday, 30 January 2009

At work, a debate broke out over MVC. In that debate, Chris Peterson commented that he hated the way things looked on the view pages, specifically with code executing in the view context. By way of example, he talked about the need for a for loop to display a collection, and how he didn't like that. Geoff Lane commented that Grails had support for this built-in.

To overcome these objections, I wrote the following simple extension method:

public static class RenderPartialCollectionExtension

{

    public static void RenderPartialCollection<T>(this HtmlHelper htmlHelper, string partialViewName, IList<T> list)

    {

        foreach (T item in list)

        {

            htmlHelper.RenderPartial(partialViewName, item);

        }

    }

}

This means that instead of the old-style View page code, like this:

<%

   foreach (Foo foo in Model)

   {

       Html.RenderPartial("~/Partials/DisplayFoo.aspx", foo);

   }

 %>

You can just write code like this:

<% Html.RenderPartialCollection<Foo>("~/Partials/DisplayFoo.aspx", Model); %>

Friday, 30 January 2009 22:40:58 (GMT Standard Time, UTC+00:00)  #    Comments [0] -
ASP.NET MVC
# Thursday, 29 January 2009

It seems that ASP.NET MVC doesn't allow for strongly-typed partial views. If anyone knows of a clean way to do it, I'd love to know!

Take the following typical page declaration:

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<Foo>" %>

This declaration allows us to access the Foo.Bar property in the view page using the following syntax: Model.Bar. This works really well, and we even get Intellisense for Foo when accessing the Model property in the editor. In contrast, if we inherited from the non-generic ViewPage, Model becomes a simple object type, which means type-casting to get to our passed in model object.

However, using partial pages with a similar technique does not work. For example, if we have a partial page (ViewPage or ViewUserControl) and call it like below, it will not allow for strong typing of the page:

Html.RenderPartial("DisplayFoo", foo)
If we try to strongly type the page, it will result in an error like this at run-time:
Parser Error Message: Could not load type 'System.Web.Mvc.ViewPage'.

One work-around is to create a code-behind file, and specify the strong typing there, and then inherit the partial page from the code-behind. But I really don't like that. RC1 made great strides to get rid of the code-behind mess, and I would prefer not to reintroduce it just for this.

Update: Thanks to bradleylandis in the ASP.NET MVC forum, he correctly figured out that I had my partial page in a folder other than the Views folder. He mentioned that you need to copy the web.config file from the Views folder to any folder that you serve view pages out of. After doing that, I now have a strongly typed partial page.

Thursday, 29 January 2009 19:22:09 (GMT Standard Time, UTC+00:00)  #    Comments [0] -
ASP.NET MVC
Navigation
Archive
<2017 October>
SunMonTueWedThuFriSat
24252627282930
1234567
891011121314
15161718192021
22232425262728
2930311234
Blogroll
About the author/Disclaimer

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2017
Dan Miser
Sign In
Statistics
Total Posts: 388
This Year: 0
This Month: 0
This Week: 0
Comments: 630
Themes
Pick a theme:
All Content © 2017, Dan Miser
DasBlog theme 'Business' created by Christoph De Baene (delarou)