Asp MVC Entity Framework and Data annotations

 

image

 

When you create a MVC view for data entry it already has the scaffolding in place to handle client side validation (and server)
However you need to specify the data annotations you need.

You’ve two options.

1) Modify the T4 code generation templates

2) Use meta data classes (this post)

The generated EF classes are partial classes, this allows us to do the following

   1:  #region Feed
   2:   
   3:      [MetadataType(typeof(FeedMetadata))]
   4:      public partial class Feed
   5:      {
   6:      }
   7:   
   8:   
   9:      public class FeedMetadata
  10:      {
  11:          [Required(ErrorMessage="Please enter a valid name for this feed")]
  12:          public string Name { get; set; }
  13:      }
  14:   
  15:      #endregion Feeds

 

Note: while mvc3 supports these annotations they are limited to [range/required/stringlength/regularexpression]. If you wish to have a bigger offering consider the extensions offered.

Here’s how.

Go the NuGet Extension Manager (right click on references and select add Library Package Reference) and search for “DataAnnotationsExtensions.”  You should see the following two packages, choose the second (includes client side validation, first is server side only.)

Btw: If NuGet is alien to you, then don’t worry, it’s basically a packet manager to make your life a littler easier… a post for another day!

SqlServer 2008 Prevent Saving changes

 

When you modify a table in SqlServer and this change requires the table to be dropped and recreated, it’s necessary that SSMS is configured to allow this.

 

image

 

Go to SSMS/Tools/Options designers and uncheck this option.

See below

 

image

Create those delete views

 

You may wonder why you would create a view for the delete action

image

 

One reason is to prevent webcrawlers interfering with your data, so create those delete views!

Using Telerik RadScheduler with MVC3

 

The cool hip thing these days is MVC, hang ur head in shame if you are still plodding along with plain old asp.net.

Actually that’s not quite right, in fact it couldn’t be further from the truth, asp.net is alive and strong and will be for a long long time, don’t mind those people complaining about

  • Not having direct (easy) control over what html gets rendered
  • Testing lets a little to be desired
  • You can’t get ur grubby little hands on the @razor (at least i’m not currently aware if it can be used outside MVC3);

ASP is alive and strong and Microsoft are actively working on it, what’s more you’ve most likely already have some pretty good controls that you slaved over or bought ready made…

I’m a bit partial to Telerik controls and tonight I wanted to use the RadScheduler in a webportal i’m working on, and here it is in action

image

 

image

So how did I manage to do this?

Well I started out with a HtmlHelper extension and then realized it was even easier.

Telerik RadScheduler works directly with webservices (please read their documentation for full info (because my posts are more pointers then full working samples)

The View contains the following (apologies in all my talk I didn’t use razor Embarrassed smile)

   1:  <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>
   2:  <%@ Register Assembly="Telerik.Web.UI" Namespace="Telerik.Web.UI" TagPrefix="telerik" %>
   3:  <asp:Content ID="HeaderCnt" ContentPlaceHolderID="TitleContent" runat="server">
   4:      
   5:  </asp:Content>
   6:   
   7:  <script runat="server">
   8:      public override void VerifyRenderingInServerForm(Control control)
   9:      {
  10:      
  11:      }
  12:  </script>
  13:  <asp:Content ID="BdyCnt" ContentPlaceHolderID="MainContent" runat="server">
  14:      <h2>Index</h2>
  15:      <telerik:RadScheduler runat="server" ID="SampleRadScheduler" EnableAdvancedForm="false">
  16:          <WebServiceSettings Path="~/Models/FeedWebService.asmx" />
  17:          <AdvancedForm Modal="false" />
  18:      </telerik:RadScheduler>
  19:  </asp:Content>

 

That’s pretty muich it, I’m using a plain old .net 2.0 style Webservice as outlined in Telerik help samples but expect I can use WCF too (another post maybe).

 

enjoy..

SqlDatasource Strict Concurrency Checking–Simplistic approach

 

Lets say you have simple UPDATE command

UpdateCommand="Update SEC_USERS SET FirstName=@FirstName, Department = @Department, Gender = @Gender”
 
 
 

Now, lets assume that two end users of your system have already requested information for SEC_USER Bill whose a male janitor.

End user 1 updates Bills Department as he’s been promoted to CEO (hey it not impossible!).
End user 2 changes Bills Gender to female.

What actually ends up happening is the End user 2 overwrites the promotion and Bill (or maybe billie now ) ends up as a female janitor.

So how can we solve this problem assuming we are using a SqlDataSource.

Here’s how:

image

  • Set the ConflictDetection property to CompareAllValues
  • Set the OldValuesParameterFormatString to xxxx_{0}
  • Update your command with a WHERE restriction for XXXX_{0}
    UpdateCommand= "Update SEC_USERS SET FirstName=@FirstName, Department = @Department, Gender = @Gender FROM SEC_USERS WHERE FirstName=@read_FirstName
     AND Department=@read_Department AND Gender=@read_Gender"

That’s it, the SqlDataSource manages the read_xxx parameters so you don’t have to.

I’ve achieved my coding certification

 

The "Works on My Machine" Certification Program

Joseph Cooney had a brilliant idea for a new application certification program. But Vista's bland white-on-gray badge, in my opinion, doesn't properly communicate the.. authoritative.. nature of said program. With the help of Jon Galloway, we zazzed things up a bit:

You might think attaining such a prestigious, rigorous level of certification would be far too challenging. But fear not! Participating in this innovative new application certification program is as simple as pressing the F5 key on your keyboard. Just follow the four easy steps Joseph outlined:

  1. Compile your application code. Getting the latest version of any recent code changes from other developers is purely optional and not a requirement for certification.
  2. Launch the application or website that has just been compiled.
  3. Cause one code path in the code you're checking in to be executed. The preferred way to do this is with ad-hoc manual testing of the simplest possible case for the feature in question. Omit this step if the code change was less than five lines, or if, in the developer's professional opinion, the code change could not possibly result in an error.
  4. Check the code changes into your version control system.

Congratulations! You're fully certified. Brand your app with your shiny new Works on My Machine badge. You'll certainly want to show it off to your fellow team members and key stakeholders. But please-- do try to keep your ego in check. Not everyone is capable of such an epic commitment to quality in software engineering.

 

source: codinghorror.

Too easy to be simple

 

Was having a conversation this evening with an ex colleague of mine, he’s recently ventured into the world of Silverlight which he loves, for him; even though it didn’t start out that way; this has become a stepping stone to the the wonderful world of web development.

Those of you that follow my blog know that I’m leaning more and more towards MVC where possible, so I ran through a demo of what’s involved dong a simple Master Details pattern with ASP MVC3 and razor and it didn’t go down all that well, sure it worked quite well but the tooling, or lack there of, was a big let down for him. Now lets recap here, back in the 90ies when I was plodding along with php/asp and iframes (*shiver*) ASP.net was being conceived; this technology was widely accepted for a number of reasons, most people may quote the postback but another one is most definitely the tooling.

As some stage in our developer life, we’ve all watched a msdn how to video etc, and the demo objective is often remarkably and simplistically achieved, either through

  • A few lines of code
  • Tooling
  • Some hocus pocus of some sort Smile.

The problem is only to know what combination of the above to apply, i.e it’s too easy to be simple. Below I outline the easy and simple way of creating a master/details page with no lines of code.

Demo

1) Open Visual Studio and create a new ASP.NET web application (I’m using .NET 4.0)

image

2) Drag a SqlDataSource onto the default.aspx webpage and configure it, I’ve chosen a database I’ve lying around, (note for membership please consider the the ASP.NET Membership API/Providers and associated schemas)

image

3) Drag a DropDownList from the toolbox and set it’s DataSourceID to be the ID you provided in the step above.
also set the DataTextField and DataTextValue to something that makes sense for your application, Here’s my generated code
<asp:DropDownList ID="lstUsers" runat="server" DataSourceID="SqlDataSourceUsers" DataTextField="NAME" DataValueField="ID" AutoPostBack="True" />

If you view your webpage now you’ll see the dropdown list populated with list of users. Now we want to populate the details part of the page,  Note: I set AutoPostBack to true, this ensures that the page is posted back each time the list selection gets changed.

4) Create another datasource and set this to the details table you wish considered.

image

5) Add a where clause setting the restriction to the selected value of the DropDownList you just created.

image

 

image

6) Now drag a GrivdView onto your page and set its datasource to the Datasource in step 5.

 

And ceca! Open your webpage in a browser now and you’ll be able to view all the workgroup id’s associated with each user.

image

Routing Regression With Two Consecutive Optional Url Parameters–(source Phil Haack)

 

It pains me to say it, but ASP.NET MVC 3 introduces an ugly regression in routing from ASP.NET MVC 2. The good news is that there’s an easy workaround.

The bug manifests when you have a route with two consecutive optional URL parameters and you attempt to use the route to generate an URL. The incoming request matching behavior is unchanged and continues to work fine.

For example, suppose you have the following route defined:

routes.MapRoute("by-day",          "archive/{month}/{day}",        
 new { controller = "Home", action = "Index",           
   month = UrlParameter.Optional, day = UrlParameter.Optional } );<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

Notice that the month and day parameters are both optional.

routes.MapRoute("by-day",          
    "archive/{month}/{day}",
    new { controller = "Home", action = "Index", 
    month = UrlParameter.Optional, day = UrlParameter.Optional } );<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

Now suppose you have the following view code to generate URLs using this route.

@Url.RouteUrl("by-day", new { month = 1, day = 23 })
@Url.RouteUrl("by-day", new { month = 1 })
@Url.RouteUrl("by-day", null)<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

In ASP.NET MVC 2 the above code (well actually, the equivalent to the above code since Razor didn’t exist in ASP.NET MVC 2) would result in the following URLs as you would expect:

  • /archive/1/23
  • /archive/1
  • /archive
  • But in ASP.NET MVC 3, you get:

  • /archive/1/23
  • /archive/1
  •  

  • In the last case, the value returned is null because of this bug. The bug occurs when two or more consecutive optional URL parameters don’t have values specified for URL generation.

    Let’s look at the workaround first, then we’ll dive deeper into why this bug occurs.

    The Workaround

    The workaround is simple. To fix this issue, change the existing route to not have any optional parameters by removing the default values for month and day. This route now handles the first URL where month and day was specified.

    We then add a new route for the other two cases, but this route only has one optional month parameter.

    Here are the two routes after we’re done with these changes.

    routes.MapRoute("by-day",         
     "archive/{month}/{day}",        
     new { controller = "Home", action = "Index"} ); 
     routes.MapRoute("by-month",          "archive/{month}",       
      new { controller = "Home", action = "Index",      
            month = UrlParameter.Optional} );<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

    And now, we need to change the last two calls to generate URLs to use the by-month route.

    @Url.RouteUrl("by-day", new { month = 1, day = 23 }) @Url.RouteUrl("by-month", new { month = 1 }) @Url.RouteUrl("by-month", null)<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

    Just to be clear, this bug affects all the URL generation methods in ASP.NET MVC. So if you were generating action links like so:

    @Html.ActionLink("sample", "Index", "Home", new { month = 1, day = 23 }, null) 
    @Html.ActionLink("sample", "Index", "Home", new { month = 1}, null)
     @Html.ActionLink("sample", "Index", "Home")<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

    The last one would be broken without the workaround just provided.

    The workaround is not too bad if you happen to follow the practice of centralizing your URL generation. For example, the developers building http://forums.asp.net/ ran into this problem as well during the upgrade to ASP.NET MVC 3. But rather than having calls to

    ActionLink all over their views, they have calls to methods that are specific to their

    application domain such as ForumDetailUrl. This allowed them to workaround this issue by updating a single method.

    The Root Cause

    For the insanely curious, let’s look at the root cause of this bug. Going back to the original route defined at the top of this post, we never tried generating an URL where only the second optional parameter was specified.

    @Url.RouteUrl("by-day", new { day = 23 })<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

    This call really should fail because we didn’t specify a value for the first optional parameter, month. If it’s not clear why it should fail, suppose we allowed this to succeed, what URL would it generate? /archive/23?  Well that’s obviously not correct because when a request is made for that URL, 23 will be interpreted to be the month, not the date.

    In ASP.NET MVC 2, if you made this call, you ended up

    with /archive/System.Web.Mvc.UrlParameter/23. UrlParameter.Optional

    is a class introduced by ASP.NET MVC 2 which ships on its own schedule outside of the core ASP.NET Framework. What that means is we added this new class which provided this new behavior in ASP.NET MVC, but core routing didn’t know about it.

    The way we fixed this in ASP.NET MVC 3 was to make the ToString method of UrlParameter.Optional return an empty string. That solved this bug, but uncovered a bug in core routing where a route with optional parameters having default values behaves incorrectly when two of them don’t have values specified during URL generation. Sound familiar?

    In hindsight, I think it was a mistake to take this fix because it caused a regression for many applications that had worked around the bug. The bug was found very late in our ship cycle and this is just one of the many challenging decisions we make when building software that sometimes don’t work out the way you hoped or expected. All we can do is learn from it and let the experience factor into the next time we are faced with such a dilemma.

    The good news is we have bugs logged against this behavior in core ASP.NET Routing so hopefully this will all get resolved in the next core .NET framework release.

    @helper / razor

     

    Here’s a neat little trick.

    Declare a helper function in your view with the @helper syntax

    image

    Note: you will get intellisense when you type the @ listing the GiveHigh5 function.

     

    Here’s the output:

    image

    enjoyThumbs up

    DRY out your MVC Views

     

    For those of you that don’t know DRY : Don’t Repeat Yourself.

    Take the following two screens

    image

    image

     

    They are nearly identical.

    MVC3/Razor provides two ways to make things DRYer.

    1) Layouts (same as asp.net master pages, not covered in this post)

    2) Partial views

    Here’s how.

    image

    Shows the create page, using the Html.Partial extension method

     

    image

    Shows the edit page, using the Html.Partial extension method on the same partial view as well

     

    image

    Shows the partial view that gets injected (for want of a better word) into the two views shown previously.