What bugs have you experience while using ASP.NET MVC?
As a first, The Html.DropDownList does not respect Selected property of SelectListItem when explicitly bound to List of SelectListItem.
What bugs have you experience while using ASP.NET MVC?
As a first, The Html.DropDownList does not respect Selected property of SelectListItem when explicitly bound to List of SelectListItem.
I don't think it's a bug, but out of the box, there's a real lack of intellisense for Models in views.
As an example:
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<MySiteMVC.Models.SiteContent>" %>
<%=Html.Encode(Model.PageTitle) //no intellisense %>
But if you wrap that in a class:
namespace MySiteMVC.Models
{
public class SiteContentFormViewModel
{
// Properties
public SiteContent SiteContent { get; private set; }
// Constructor
public SiteContentFormViewModel(SiteContent sitecontent)
{
SiteContent = sitecontent;
}
}
}
You will then have Intellisense:
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<MySiteMVC.Models.SiteContentFormViewModel>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
<%=Html.Encode(Model.SiteContent.PageTitle) //Intellisense Present %>
As I understand it, Views use reflection to show Models, which is what causes the lack of intellisense -- but I think that if a product uses 'convention over configuration', then this method of making classes ought to be considered 'convention' and tossed in when you make a new Model.
Updating a Model in LINQ-to-SQL Fails But Doesn't Throw Exception
If you try to update a LINQ-To-SQL Model that doesn't have a primary key defined (normally because you forgot to define one in your database table); the UpdateModel()
method doesn't work. It also doesn't throw an error or exception. It happily tries, fails, and doesn't tell anyone.
Arguably this is not a bug, but in either case it can cause some very unexpected behavior :
Lets say you have an action method to display products in a shopping cart
// ProductsController.cs
public ActionMethod Index(string gender) {
// get all products for the gender
}
Elsewhere, in a masthead that is displayed on every page you are using Url.RouteUrl
to create HREF links to other pages on the site :
<a href="<%= Url.RouteUrl("testimonials-route", new { }) %>" All Testimonials </a>
This testimonials-route
is defined in global.ascx
by the first route below.
Notice that the above call to RouteUrl
does not provide a gender
, but the route is defined with a default of 'neutral' so we'd expect Testimonials.Index("neutral") to be called.
routes.MapRoute(
"testimonials-route",
"testimonials/{gender}",
new { controller = "Testimonials", action = "Index", gender = "neutral" },
new { gender = "(men|women|neutral)" }
);
routes.MapRoute(
"products-route",
"products/{gender}",
new { controller = "Products", action = "Index", gender = (string)null },
new { gender = "(men|women|neutral)" }
);
If someone visits the page /products/women
we get an HREF to /testimonials/women
If someone visits the page /products
then we get an empty HREF (the call to RouteUrl returns null).
But that doesn't make sense does it? testimonials-route
is supposed to default to 'neutral'
for us if we don't provide a route value for it?
What turns out is happening is that Url.RouteUrl(routeName, routeValues)
helper extension will first look in its routeValues
parameter for a gender
route value and if it doesn't find it in that dictionary it will look at the current URL that we're on (remember that Url is a UrlHelper object which has the context of the current request available to it).
This has a possibly nice effect of giving us a link to men's testimonials if we're on a mens product page, but that probably isnt what we want if we haven't passed a value in the RouteUrl
call, and explicitly specified 'neutral' as a default in the global.asax.cs
file.
In the case where we visited /products/
we triggered the 'products-route'
route and the Products(null)
method was called. The call to Url.RouteUrl()
actually inherits THIS null value for gender
when we're creating a URL using testimonials-route
. Even though we have specified a default for gender
in 'testimionials-route
' it still uses this null value which causes the route to fail and RouteUrl
returns null. [note: the route fails because we have a constraint on (men|women|neutral) and null doesn't fit that]
In this case once you've figured it out you can fix it quite easily in numerous ways, but it could in other cases cause some dangerous behavior. This may be by design, but its definitely scary.
My solution was this :
public static string RouteUrl(this UrlHelper urlHelper, string routeName, object routeValues, bool inheritRouteParams)
{
if (inheritRouteParams)
{
// call standard method
return urlHelper.RouteUrl(routeName, routeValues);
}
else
{
// replace urlhelper with a new one that has no inherited route data
urlHelper = new UrlHelper(new RequestContext(urlHelper.RequestContext.HttpContext, new RouteData()));
return urlHelper.RouteUrl(routeName, routeValues);
}
}
I can now do :
<a href="<%= Url.RouteUrl('testimonials-route', new { }, false)%> " Testimonials </a>
and know for sure it will always behave the same way no matter what the context.
The way it works is to take the existing UrlHelper
and create a new one with blank 'RouteData'. This means there is nothing to inherit from (even a null value).