|
|
These blog entries are written by industry experts and leaders. We consider this content to be a good read for any software developer or web technologist.
July 2009 - Posts
-
The ASP.NET team just released the first public preview of ASP.NET MVC Version 2. You can download it here. Today’s preview works with .NET 3.5 SP1 and VS 2008, and can be installed side-by-side on the same machine as ASP.NET MVC 1.0 (meaning they don’t conflict and your existing ASP.NET MVC 1.0 projects will not be impacted if you install it). If you have both ASP.NET MVC 1.0 and ASP.NET MVC 2.0 installed you’ll see two ASP.NET MVC project templates within Visual Studio 2008’s “New Project” dialog:  The release notes that come with the ASP.NET MVC 2 Preview release detail how to upgrade existing ASP.NET MVC 1.0 projects to use V2 if you’d like to migrate them forward to take advantage of the new features. New Features ASP.NET MVC V2 will include a bunch of new capabilities and features (some of these have already been called out on the ASP.NET MVC roadmap page). Today’s “Preview 1” release contains a first look at some of the new features. Many more features will show up in future preview builds. The Preview 1 bits are still relatively early - the team is releasing today’s build to start receiving and incorporating feedback. Below are some quick details about some of the new Preview 1 capabilities: Areas Support ASP.NET MVC 2 includes support for a new feature called “areas” that allow you to more easily partition and group functionality across an MVC application. Areas provide a means of grouping controllers and views to allow building subsections of a large application in relative isolation to other sections. Each area can be implemented as a separate ASP.NET MVC project which can then be referenced by the main application. This helps manage the complexity when building a large application and facilitates multiple teams working together on a single application together. Below is a screen-shot that shows a single solution that has three projects. One of the projects is named “CompanySite” and includes the core site content, layout and controllers and views. There are then two separate “Area” projects - “Blogs” and “Forums”. These projects implement the functionality that exists under the /Blogs and /Forums URL sections of the site – and encapsulate all of the routing rules, controllers and views implementing these sections:  The Preview 1 release includes the first part of the areas feature implementation. It doesn’t include any tool support yet (right now you need to manually add a build task to create an area project and set it up). Future preview releases will include tooling support, and expand and refine the feature-set further. DataAnnotation Validation Support ASP.NET MVC 2 now includes built-in support for the DataAnnotation validation support that first shipped with .NET 3.5 SP1 – and which is used with ASP.NET Dynamic Data and .NET RIA Services. DataAnnotations provides an easy way to declaratively add validation rules to Model and ViewModel classes within an application, and have automatic binding and UI helper validation support within ASP.NET MVC. To see this feature in action, we can create a new “Customer” ViewModel class like below that has five properties on it (implemented using the C# automatic property feature).  We can then decorate the properties with appropriate validation rules using the DataAnnotation attributes implemented within the System.ComponentModel.DataAnnotations namespace. The code below uses 4 different built-in validation rules – [Required], [StringLength], [Range], and [RegularExpression]. The namespace also includes a base class (ValidationAttribute) that you can subclass to create your own custom validation attributes.  We can then create a CustomersController class that has two Create action methods on it. The first Create action method handles HTTP GET requests to the “/Customers/Create” URL, and renders a view template based on an empty Customer object. The second Create action method handles HTTP POST requests to the same URL (and takes a Customer object as a method parameter). It checks if there are any model binding errors to the input submitted, and if there are errors it redisplays the view template using the already entered data. If there are no errors it displays a success view to the user:  Finally, we can right-click within either of the Create action methods above, choose the “Add View” context menu command, and automatically “scaffold” a “create” view template that is based on the Customer object. When we do this the generated scaffolded view template will contain the below HTML <form> for our Customer:  And now when we request the “/Customers/Create” URL in our browser we’ll get an initial empty form like below:  If we enter invalid input and perform a post to the server, the ASP.NET MVC 2 model binder will detect that there are DataAnnotations attributes on our Customer class, and automatically validate the posted form input using them. If there are errors our controller action method redisplays the form – which will cause the appropriate validation error messages to be rendered to the user like below. Note how the validation property error message strings we specified using the DataAnnotation attributes are displayed to the user by the Html.Validation helper methods. No extra code is required to enable this.  The above form will redisplay with error messages each time the user enters invalid input and attempts to perform a form post. In a future ASP.NET MVC 2 preview we are planning to ship the jQuery Validation plugin as part of the default project template, and add support for the automatic client-side JavaScript enforcement of DataAnnotation validation rules as well. This will enable developers to easily add validation rules in one place on either a Model or ViewModel object, and have them be enforced both client and server-side everywhere it is used within the application. If you do not wish to annotate your model or viewmodel classes directly, you can alternatively create a “buddy class” that accompanies your model class and encapsulates the DataAnnotaton rules separately. This capability is also useful for scenarios where VS is code-generating/updating the properties on a class directly and you cannot easily add attributes to the generated code (for example: classes generated by the LINQ to SQL or LINQ to Entities designers). In addition to providing built-in support for DataAnnotations, the DefaultModelBinder class in ASP.NET MVC V2 now has new virtual methods that can be overridden to easily integrate other validation frameworks as well (for example: Castle Validator, EntLib Validation, etc). The validation UI helper methods in ASP.NET MVC are designed to support any type of validation framework (they have no direct knowledge of DataAnnotations). Strongly Typed UI Helpers ASP.NET MVC V2 includes new HTML UI helpers that enable you to use strong-typed lambda expressions when referencing the view template’s model object. This enables better compile-time checking of views (so that bugs can be found at build-time as opposed to runtime), and also enables better code intellisense support within view templates. You can see an example of the better intellisense in action below – notice how I am getting a full listing of the customer model object’s properties when using the new Html.EditorFor() helper method:  Preview 1 has built-in support for new Html.EditorFor(), Html.LabelFor(), and Html.DisplayFor() helpers. An updated MVC futures assembly that we are shipping this week adds additional Html.TextBoxFor(), Html.TextAreaFor(), Html.DropDownListFor(), Html.HiddenFor(), and Html.ValidationMessageFor() helper methods as well (overtime these will move into the core ASP.NET MVC 2 assembly too). Below you can see an updated version of the “create” view template for our customer creation scenario. Notice how instead of using string expressions to reference the customer object we are instead using strongly-typed lambda expressions with the UI helpers. We can get full intellisense and compile-time checking with all of them:  The Html.LabelFor() helper method above generates <label for="Name">Name:</label> HTML markup. The Html.EditorFor() helper method can be used for any datatype value. By default it is smart and will output an appropriate HTML <input/> element based on the type to be edited. For example, it will generate <input type=”text”/> elements for the first four properties above (which are strings and integers). It will generate a <input type=”checkbox”/> element for the final “IsActive” property – which is of type boolean. In addition to supporting simple data-types, the Html.EditorFor() helper method also allows you to pass more complex objects with multiple properties to it. By default it will loop over the public properties of the object and generate a <label>, <input/> element, and any appropriate validation message for each property it finds. For example, we could re-write the above view to have just a single Html.EditorFor() call for the Customer object to conceptually output the same markup as above:  The strongly typed helpers allow you to optionally decorate the properties of the Customer ViewModel class with [DisplayName] attributes to control the label string that is output for each property used (for example: instead of having a label text of “IsActive” we could apply a [DisplayName(“Is Active Customer:”)] attribute). You can also add [ScaffoldColumn(false)] attributes to indicate that a particular property shouldn’t be rendered at all in scenarios like above where complex objects are passed to Html.EditorFor(). UI Helper Templating Support The Html.EditorFor() and Html.DisplayFor() helper methods have built-in support for rendering both standard data-types as well as complex objects with multiple properties. As noted above, they also support basic customization of rendering by applying attributes like [DisplayName] and [ScaffoldColumn] to the ViewModel. Often developers want to be able to customize the output from UI helpers even further, though, and have total control over what is generated. The Html.EditorFor() and Html.DisplayFor() helper methods support this via a templating mechanism that allows you to define external templates that can override and completely control the output rendered. Better yet, you can customize the content rendered on a per-datatype/class basis. With Preview 1 you can now optionally add an “EditorTemplates” and/or “DisplayTemplates” folder underneath either a \Views\[controllername] directory (if you want to customize the rendering for views used by a specific controller) or underneath the \Views\Shared folder (if you want to customize the rendering for all views and controllers in an application). You can then add partial template files to these folders to customize the output rendering performed on an individual datatype and/or class basis. For example, below I have added an EditorTemplates folder underneath the \Views\Shared folder – and added three custom template files to it:  The “Customer.ascx” template above indicates that I want to customize the output anytime Html.EditorFor() is passed a Customer object (for example: I could customize the exact ordering/layout of the Customer properties). The “DateTime.ascx” template above indicates that I want to customize the output anytime Html.EditorFor() is passed a DateTime property (for example: I might want to use a JavaScript datepicker instead of a plain textbox). I could optionally add an “Object.ascx” template to the folder if I wanted to override the default rendering of all objects. In addition to customizing rendering on a per-type basis, you can also add “named templates” to the folder. A common scenario might be a “CountryDropDown” template that handles a string datatype – but instead of providing a standard textbox instead renders a <select> dropdownlist of country values that a user can pick from. Below is what this editor template might look like:  We can explicitly indicate that we want to use the above template by passing its name as an argument when we invoke the Html.EditorFor() helper method. For example, below in addition to specifying a lambda expression for our Country property, we are also specifying the name of the editor template to use when rendering it:  Alternatively, you can specify “UIHint” attributes on your ViewModel properties and types. This allows you to indicate the default editor or display template to use in a single place, and have it be used in all views across your application (without having to explicitly pass it as an argument to Html.EditorFor). Below is an example of how to indicate using a UIHint attribute that the Customer.Country property (which is of type string) should by default use the CountryDropDown template when being rendered:  Once we set the above attribute on our ViewModel we no longer need to specify a template name explicitly when we use that property with Html.EditorFor(). And now when we hit refresh on our /Customers/Create URL our Country property will be rendered as a dropdown instead of a standard textbox:  Other Cool Features ASP.NET MVC 2 Preview 1 includes a number of other small, but really nice, feature additions. A few of my favorites include: New [HttpPost] Attribute It is pretty common with ASP.NET MVC to split up the handling of a URL across two action methods – one that handles GET requests and one that handles POST requests. With ASP.NET MVC 1 you used an [AcceptVerbs(HttpVerbs.Post)] attribute to indicate the “Post” version of an action method:  This still works with ASP.NET MVC 2. Alternatively, though, you can also now take advantage of a terser [HttpPost] attribute that does the same thing:  Default Parameter Values Handling optional parameters is a pretty common web scenario. With ASP.NET MVC 1 you could handle optional parameters either by registering a custom routing rule and specifying a default value with it, or by marking an action method parameter as nullable and then adding code within your action method to handle whether it was null (and if so provide a default value). ASP.NET MVC 2 Preview 1 now supports decorating action method parameters with the DefaultValueAttribute from the System.ComponentModel namespace. This allows you to specify a parameter value that ASP.NET MVC should pass in if it is not present as part of the request. For example, below is an example of how we could handle both the /Products/Browse/Beverages and /Products/Browse/Beverages?page=2 URLs – and have the “page” parameter value be “1” if it isn’t provided as part of the querystring:  VB today allows you to specify default parameter values directly within the VB language (avoiding the need to explicitly specify the DefaultValue attribute like above). C# in VS2010 will also support default values with optional parameters – which will enable you to rewrite the above code simply as:  This should make handling default/optional scenarios really easy and clean. Binding Binary Data ASP.NET MVC Preview 1 adds support for binding base64-encoded string values to properties of type byte[] and System.Data.Linq.Binary. There are now two overloaded versions of Html.Hidden() that can take these data-types. These can be useful for scenarios where you want to enable concurrency control within your application and want to roundtrip timestamp values of database rows within your forms. Summary Click here to download a .zip file that contains a ASP.NET MVC 2 project that implements the sample code I demonstrated in the above walkthrough. Today’s build of ASP.NET MVC 2 is just a first preview. More features will be coming in future previews, and the team expects to get a lot of feedback on ways to improve and enhance the release. The goal with doing these regular previews is to help make sure that this feedback process is open and that anyone who wants to participate can easily get involved. Please post any feedback, suggestions or problems you have to the ASP.NET MVC Forum on www.asp.net. You can also learn more about the release from Phil Haack’s MVC2 post, and from the Channel9 video Phil did with Scott Hanselman about the Preview 1 release. Hope this helps, Scott P.S. I have been using Twitter more recently to-do quick posts and share links. You can follow me on Twitter at: http://www.twitter.com/scottgu (@scottgu is my twitter name) 
|
-
My Toolbox column in the August 2009 issue of MSDN Magazine is available online and includes the following reviews:
- SQL Sets - SQL Sets is a neat tool that allows you to save database queries in a self-contained, portable file format. In a nutshell, you can run a database query, save the results into a file, and then email the file to a colleague who can annotate, sort, filter, and explore the results without needing access to the database or having any knowledge of the SQL syntax. It's a nifty tool for for sharing data with stakeholders without giving them access to the database; it can also be used to compare sets or as a tool for archiving data.
- Blogs of Note: Stephen Walther on ASP.NET MVC - every developer using ASP.NET MVC should subscribe to author, speaker, and Microsoftie Stephen Walther's blog. They you'll find more than 50 in-depth detailed tips on using ASP.NET MVC along with end-to-end tutorials, and sample chapters from his books.
- Visual SVN Server - Subversion is a popular and free source code control application. Unfortunately, getting started with Subversion entails a bit of a learning curve. For example, in order to access the Subversion repository over HTTP you need to install and configure the Apache web server. Moreover, many of Subversion's configuration options require tinkering with text-based configuration files. Visual SVN Server is a free product that makes using Subversion as easy as point and click. With a few clicks of the mouse, Visual SVN Server will install and configure Subversion (and Apache) for you. And, once installed, it offers a GUI interface for creating and managing repositories and users.
- NArrange - NArrange is a free, open source tool that automatically rearranges your C# or Visual Basic source code into a more readable format. From the review: 'By default, NArrange groups constructors, fields, properties, methods, and events into regions and alphabetizes the members within each region. Consecutive blank lines are removed, tabs are converted into spaces, and the using or Import directives within a class file are consolidated and sorted.' You can have NArrange rearrange a particular file, all files in a directory, or all files in a Visual Studio Project or Solution, and NArrange can be launched from the command-line or from within Visual Studio.
This issue did not include a book review.
Enjoy! - http://msdn.microsoft.com/en-us/magazine/ee294454.aspx
As always, if you have any suggestions for products, blogs, or books to review for the Toolbox column, please send them to toolsmm@microsoft.com.
|
-
Most Internet-facing websites that support user accounts allow visitors to register an account on their own. Take a site like Facebook, for example. A visitor who wishes to create a new account may do so by visiting the registration page, choosing a username and password, and entering their email address. Implementing such a workflow in an ASP.NET application is relatively straightforward: enable Membership and then create a registration web page, using a CreateUserWizard control to collect user input and create the new account. Out of the box, the CreateUserWizard control prompts a registering user for their username, password, email address, and security question and answer, and then creates a new account and signs the user in once the process completes.
Like the othe Login-related Web controls, the CreateUserWizard can be customized both in its appearance and behavior. There are articles on 4Guys, like Customizing the CreateUserWizard Control, that show how to configure the CreateUserWizard control to include additional questions to the registering user. Examining ASP.NET's Membership, Roles, and Profile - Part 11 explores how to verify a new user's email address by requiring them to click on a link sent in an email message before being signing in for the first time. It's also possible to use the CreateUserWizard control to create user accounts for other people. This is useful for websites that don't allow anonymous users to register, but rather require that the site's administrators manually create each user account.
I recently got an email from a reader who had a site where user accounts were created by a site administrator. Upon creating the account, the new user would receive an email with the username and password the administrator chose for them, along with a link to the sign in page. What this reader wanted to do was require these new users to immediately change their password after signing in for the first time. This functionality is easy to implement with a slight enhancement to a previous article of mine.
Examining ASP.NET's Membership, Roles, and Profile - Part 16 shows how to set up a password expiry policy for an ASP.NET application that uses Membership. In a nutshell, the Membership system exposes a particular user's last password changed date/time via the MembershipUser class's LastPasswordChangedDate property. To quote from the article: “This property is set to the current date and time when the user account is first created or whenever the user changes her password.”
Part 16 shows how to create a page where the user can change their password as well as how to determine if the user's password has expired when they sign on. This latter task is accomplished by creating an event handler for the Login control's Authenticate event and verifying that the number of days since the user last changed their password has not exceeded the password expiry window:
Protected Sub myLogin_Authenticate(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.AuthenticateEventArgs) Handles myLogin.Authenticate 'Are the credentials valid? If Membership.ValidateUser(myLogin.UserName, myLogin.Password) Then 'Has the password expired? Dim usrInfo As MembershipUser = Membership.GetUser(myLogin.UserName)
Dim daysSincePwdChange As Integer = Convert.ToInt32(DateTime.Now.Subtract(usrInfo.LastPasswordChangedDate).TotalDays) If daysSincePwdChange > SecurityUtils.DefaultPasswordExpiryInDays Then 'Password expired, send user to change password Response.Redirect("~/ChangePassword.aspx?UserName=" & Server.UrlEncode(myLogin.UserName)) Else e.Authenticated = True 'Credentials valid & password is current End If Else e.Authenticated = False 'Invalid! End If End Sub
To force new users to change their password upon signing in for the first time, simply add a condition to the If statement to check whether the user's CreationDate and LastPasswordChangedDate properties are one in the same:
If daysSincePwdChange > SecurityUtils.DefaultPasswordExpiryInDays OrElse userInfo.CreationDate = userInfo.LastPasswordChangedDate Then ...
That's it!
|
-
I recently had a client with an urgent issue with a legacy classic ASP web application - users to his site were getting logged out immediately after logging into the site, or after visiting one or two pages. As with most classic ASP applications, user authentication information was being persisted in session state so this symptom implied that session state was not being maintained.
Session state problems usually arise from one of two causes:
- The user is not properly maintaining the session token. By default, the web server is able to associate a user with a particular session store through the use of a SessionID value that is stored on the user's browser via a cookie. Each time a user makes a request to the server, this cookie is sent along and, lo, the web server knows the user's SessionID. If the user's browser is configured to reject cookies, or if there is a proxy or firewall on the user's side that is stripping out this cookie, then each time the user makes a request to the server it will appear as if it's the user's first request and the server will generate a new SessionID and a new cookie for the user.
- A proxy server or firewall on the web server side is stripping out the cookie. It may be that the user is correctly storing and sending the session cookie, but that the hardware on the web server's side is stripping out the cookie before it can be read by the ASP or ASP.NET engine, causing the server to generate a new SessionID and a new cookie for the user on each request.
To narrow down the cause of the session problem, the first step is to fire up Fiddler and examine the HTTP traffic when visiting the site through a browser. In particular, look at the HTTP headers to see the Set-Cookie values sent from the server to the browser, and the Cookie value sent from the browser to the server. In running these initial tests, I saw that the browser was clearly sending the SessionID cookie to the server, but that the server was responding with a new SessionID cookie on most requests. However, every now and then the server would not send back a cookie at all, as if it had correctly identified the user by their SessioniD. Hrm....
My first inclination was to make sure that there was no hardware of software stripping out the cookie before it reached the server. To test this, create a page that dumps out the server variables to the screen, which include the cookies sent by the browser. (For code to do this in classic ASP, see: Using the Request.ServerVariables Object; for code in ASP.NET, see: Iterating Through ServerVariables in ASP.NET and C#.) If there was something stripping out the session cookie then when visiting this page through a browser I should see two things: in Fiddler I should see that the browser sends a Cookie HTTP Header, but in the output of the web page that lists the server variables I should not see that cookie information in the HTTP_COOKIE server variable.
However, when I ran the above test I did see the cookie values. So the browser was correctly storing and sending the SessionID cookie, the server was receiving it, but for some reason it was creating a new session store on (almost) every request. What was going on?
After nearly two hours of searching the Internet and poking through IIS settings, it finally became clear - the client had configured the IIS Application Pool to use a 20-thread web garden. When you use a web garden you instruct IIS to spin up multiple worker processes to handle incoming requests. The idea is that each worker process can be migrated to a different core on a multi-core CPU and thereby improve scalability, performance, and reliability. (Nicholas Piasecki has an excellent overview of web gardens, their benefits, and common pitfalls over at his blog: On Web Gardens, ASP.NET, and IIS 6.0.) One potential issue with web gardens is that they do not support InProc Session State, as with InProc Session State the session data is stored in the same memory space as each worker process.
What was happening with this client is that when a user visited the site the request would be randomly dispatched to one fo the worker processes in the garden and it would create (and store) session state for that user, sending back a valid SessionID value. When the user went to the next page the browser sent back the SessionID as expected, but there was a 19/20 chance (95%) that the user would be sent to a different worker process in the garden. This different worker process would not have access to the session store in the original worker process and would therefore create a new session store and create a new SessionID cookie.
In ASP.NET you can configure session state to use the OutOfProc setting, which stores session data using a state server rather than at the worker process level; alternatively, you could configure session state to store session in SQL Server. Either configuration could be used to have session state work in a web garden. With classic ASP applications, there are no configuration options for session state storage. Consequently, the only fix was to disable the web garden. And anyway, I think that setting was made accidentally, as I don't know why this client would want to suddently increase the number of worker processes from 1 to 20, as this web application is hosted on a dedicated server and gets at most a few dozen unique users per day.
Long story short, the vast majority of session state problems center around the cookie not being properly saved by the client or by the server not getting the cookie due to some hardware or software stripping it out of the incoming request. But if you've exhausted those avenues, be sure to check the web garden setting for the application pool. It may save you a couple of hours! :-)
|
-
Pingback from Property with Formula (generated=always) generates invalid SQL for post-insert Select | rapid-DEV.net

|
-
If you try some of the traditional ASP.NET approaches to localization and internationalization in an MVC application you’re likely to run into a couple interesting* obstacles. Resx Files In App_GlobalResources Using resource files in App_GlobalResources from your controller code will break your unit tests When you drop a .resx file in the special App_GlobalResources folder, the IDE uses the GlobalResourceProxyGenerator to generate a strongly typed internal class to wrap the resources inside. The internal class gives any code in the MVC project access to the resources: var greeting = Resources.Strings.Greeting;
You can also use the resources from a view: <%= Html.Encode(Resources.Strings.Greeting) %>
The problem is that global resources are not actually embedded into the project’s .dll. Instead it is the ASP.NET runtime that creates an App_GlobalResources assembly with the resources inside. This assembly is referenced by all the view assemblies ASP.NET creates, and is explicitly loaded by the strongly typed wrapper generated by the GlobalResourceProxyGenerator. Since the App_GlobalResources assembly doesn’t exist without an ASP.NET compilation phase, it’s not available when unit tests are running. Controller code under test that tries to access the resources will bomb with an exception.
Note that you’ll also have some Intellisense problems when using the view syntax shown above. I'm guessing this is because the IDE is confused by seeing the resource wrapper in two places (the project assembly, and a wrapper also goes into the App_GlobalResource created by ASP.NET in the Temporary ASP.NET Files folder. ).
There is a way to make resx files in App_GlobalResources work, but the folder isn’t truly necessary in an MVC project (or a web application project, for that matter). I think it’s just as easy to add resx files in a different location, even a separate class library, to avoid any confusion on how App_GlobalResources will behave.
In short: avoid App_GlobalResources and App_LocalResources (which has its own set of problems) in MVC.
Resx Files Outside Of Special Resource Directories
If you add a resx file to any other folder in an MVC project or class library, the resx is automatically set to be embedded into the project’s output assembly - this is good. The IDE also assigns the resx a custom tool of ResxCodeFileGenerator to generate a strongly typed wrapper - this is good. The generated class is internal by default – this is bad. The assembly created for a view (by ASP.NET) won’t be able to use the internal class because it is in a different assembly – the project assembly compiled in Visual Studio.
Solution
The easy fix is to make sure the custom tool is set to PublicResXFileCodeGenerator instead of ResXCodeFileGenerator. You can do this in the property window for the file, or in the resource editor that gives you a drop down for “Access Modifer” (the options are Internal, Public, and No Code Generation – choose Public).
You can also set the “Custom Tool Namespace” for the generated wrapper in the properties window. My suggestion is to use a convention like “Resources” for global resources, and “Resources.Controller.View” for resources dedicated to a specific view.
This approach means you can use the resources in unit-testable controller code, and in views, too. The syntax remains the same as above. The ResouceManager used in the wrapper classes can automatically resolve the proper resource to use depending on the current UI culture setting of the thread.
Setting The UI Culture
The easiest approach to having the correct UI culture in effect during web request processing is to use the globalization section of web.config. <globalization uiCulture="auto" culture="auto"/>
The above will set both the current UI culture and current culture settings for the request. See Dennis Dietrich’s post for a good explanation of the two settings: YACVCP (Yet another CurrentCulture vs. CurrentUICulture post).
If you need to set the culture up according to a user’s preference, or a URL parameter, then the best bet is to write a custom HTTP module or action filter.
* Interesting only if you consider localization and resource files interesting, in which case you might need to take some medication. 
|
-
Today we officially shipped the final release of Silverlight 3. Silverlight 3 Features Silverlight 3 is a major update and delivers a ton of new features and capabilities. Some of the new Silverlight 3 runtime capabilities include: HD Media Silverlight 3 now supports hardware graphics acceleration – enabling both video and graphics compositing to be offloaded onto a GPU. This can dramatically lower CPU usage on a computer, and enables HD video to be played on older low end machines. You can now deliver and play 1080p HD video experiences over the web. Silverlight 3 includes new media codec support for H.264 video, AAC audio and MPEG-4 content. This enables you to easily play and stream media encoded using these standards. Silverlight 3 also includes raw bitstream audio/video APIs that enable you to create additional codecs (in any .NET language) that support playing any other media format. Silverlight 3 also adds a variety of additional media features that enable better logging (for media analytics and ad monetization scenarios), provide the ability to disable screen-savers when playing long-form video content, and enable content protection. IIS Media Services is a free server product that complements Silverlight and provides the ability to efficiently stream media over HTTP. It enables both on-demand and live HD video to be delivered using “smooth streaming” - which is an adaptive streaming algorithm that can deliver video at bitrates optimized for a client’s network conditions and CPU capabilities. Check out this demo to see a good example of smooth streaming in action with Silverlight. The HD support within Silverlight, combined with the Smooth Streaming support of IIS Media Services, enables a dramatically better video experiences on the web. This past week alone, we’ve had multiple customers broadcast live HD events using Silverlight and smooth streaming (up to 3MBits) including: Wimbledon, the Tour de France, AVP Volleyball, and the Michael Jackson Memorial Service. Immersive Graphics The new GPU acceleration capabilities of Silverlight 3 enable even richer and more immersive graphic experiences. Silverlight 3 also adds new perspective 3D support that can be used with graphic elements, videos and controls. Silverlight 3 also includes new bitmap and pixel APIs, as well as the ability to create and apply custom pixel shader effects (e.g. blur, dropshadow, swirl, etc) to any image, video element, or control. Easing support can also now be used to enable more textured motion within animations. Out of Browser Support Silverlight 3 enables applications to run outside the browser and taken offline. Users can safely install web applications on their computers, and create persistent shortcuts to them on the desktop, start menu and taskbar (this is supported on both Windows and the Mac). New network detection support within Silverlight enables developers to monitor the network status of a machine and switch between offline and online modes within their applications. Silverlight 3 also includes an automatic update mechanism for applications – so that clients who have installed applications are automatically updated when new application versions are deployed on the originating webserver. Application Development Silverlight 3 includes a ton of new application development features. The Silverlight 3 runtime/SDK combined with the Silverlight Toolkit now includes ~100 UI controls that enable common scenarios (layout, data, charting, child windows, etc) while also providing full styling and template customization support. Silverlight 3 enables richer data binding features. Element to element binding support between controls is now enabled. Validation error template support has been added to controls (enabling better error message display). Hierarchical data binding is supported by the DataGrid. And a new DataForm control enables better master/detail scenarios. Silverlight 3 also now enables SaveFileDialog support. Silverlight 3 includes a new navigation framework that enables deep-linking and forward/back button integration within the browser. This also enables search engine optimization (SEO) support so that content within a Silverlight application can be indexed by search engines – including Google, Bing and Yahoo. Silverlight 3 also supports the ability to cache assemblies on the client, and re-use them across multiple applications (decreasing the download size and improving the startup time of applications). Silverlight 3 includes much better text rendering and font support. Text rendered using Silverlight 3 applications is much crisper and cleaner than previous releases, and applications now have access to local fonts. The Silverlight 3 styling system also now supports merged resource dictionaries, BasedOn style inheritance support, and the ability for styles to be reset any number of times. Silverlight 3 also adds richer accessibility support, and is the first browser plug-in to provide access to all system colors, allowing partially-sighted people to make changes such as high contrast color schemes for ease of readability using familiar operating system controls. Silverlight 3 includes richer networking support. WCF error faults are now supported across the network. Server-side push duplex support is now easier to setup. Binary XML serialization of payloads is now supported. The new .NET RIA Services framework (which now has a go-live license) can be used to easily build multi-tier data applications that span the client and server. .NET RIA Services enables you to write validation code once and have it applied on both the client and middle-tier layers of your applications. Visual Studio 2008 Tools for Silverlight 3 Today we are also shipping a free download that enables Silverlight 3 development support for VS 2008 and Visual Web Developer 2008 Express (which is free). The VS 2008 Tools for Silverlight download provides project support, intellisense, compilation, and debugging for Silverlight 3 applications. The next release of Visual Studio - VS 2010 - will add to this and provide a fully interactive WYSIWYG designer for Silverlight (including data binding support within the designer). Click here to download the VS 2008 Tools for Silverlight (this will also install the SL3 developer runtime + sdk). Click here to download the Silverlight Toolkit (which adds additional controls). Expression Studio 3 Today we are also shipping a release candidate (RC) of Expression Blend 3 (including Sketchflow) that enables rich editing of Silverlight 3 applications and projects. You can download the Expression Blend 3 + Sketchflow RC here. Expression Blend 3 is a major update and enables dramatically richer tooling support. Some of its improvements include: - Sketchflow: SketchFlow makes it significantly easier to create prototypes, experiment with dynamic user experiences, and incorporate feedback from customers. If you haven’t seen or tried it yet - you must. It really is a game changing new way to create great user centric applications.
- Intellisense: Blend 3 includes C#, VB and XAML intellisense support. You can now write code and event handlers within Blend without having to switch to VS.
- Behaviors: Blend 3 includes behavior support which can encapsulate complex design interactions into reusable components that can be directly applied to a control within the design surface. This enables designers to quickly add functionality and behavior to applications without having to write code.
- Adobe Photoshop and Illustrator Import: Blend 3 now has built-in support for importing Photoshop and Illustrator files. As part of the import process you can view and pick individual Photoshop layers to import, customize and regroup layers, and have Photoshop/Illustrator elements retain their original formats within XAML: including layer positions, editable text and font settings, and vector element conversion to XAML.
- Sample Data: Blend 3 adds design-time sample data support which makes it easy to mock up data-connected applications and see what they look like without requiring access to live data. You can generate sample data or import sample data from an XML file and it is available to controls on the artboard at design-time. You can customize your sample data details, and you can easily switch between using sample data and using live data at run-time.
- TFS: Blend 3 now includes Team Foundation Server (TFS) support – allowing you to use source control and enlist within projects. Blend shares the same project and solution format as Visual Studio – allowing both VS and Blend to work simultaneously on the same projects and enabling seamless editing between them.
- Other Improvements: Additional enhancements including improved animation and easing function support, 3D transform support, visual effects support, and an improved visual state manager designer.
Christian Schormann has a great blog post that describes Expression Blend 3 in more detail. The final release of Expression Studio 3 (which includes the Blend + Sketchflow, Web, Encoder and Design products) will ship within the next 30 days. Expression Studio 3 will be included as part of the MSDN Premium and higher subscriptions (meaning MSDN Premium customers don’t have to pay anything extra to get all of the Expression Studio products). Expression Studio 3 will also be available for standalone purchase for $599 (with discounts available for upgrades from previous versions of Expression and/or competitive products). Summary Today’s release is a major update of our Silverlight stack of products – and comes only 9 months after the release of Silverlight 2. You can learn more about Silverlight 3 and the tools that go along with it from the below sites: Hope this helps, Scott 
|
-
Error Logging Modules And Handlers (ELMAH) is a free, open source error logging library for ASP.NET applications that provides automated error logging and notification and, unlike health monitoring, offers a built-in log viewer web page along with a host of other nifty features. If you're not using ELMAH or have never heard of it I highly recommend that you check it out. It's the first thing I add to any new ASP.NET project I start.
As with any sort of logging service is is important that ELMAH's log be periodically pruned. If you let ELMAH's log grow unchecked it can reduce performance when querying the log and suck up disk space, which is especially important in hosted environments where there are typically hard disk quote limits for each user on the database server. The good news is that there are a number of techniques you can employ to help ensure that your ELMAH error log stays a reasonable size.
- Use error filtering. ELMAH offers a rich set of error filtering rules that you can use to instruct ELMAH not to log certain types of errors, which can help keep ELMAH's log size down. I use error filtering to filter out 404 errors. While logging 404 errors can alert you to broken URLs on your site or others, if you've ever managed an Internet-facing website you know that it's not uncommon to receive a deluge of requests from bots searching for security holes.
- Setup a weekly job in SQL Server. If your website is hosted in a dedicated environment you can (likely) setup a job on SQL Server. In past projects I've used a job that ran once a week on Sunday at 2:00 AM that would delete all ELMAH log entries older than three months.
- Update the ELMAH_LogError stored procedure to delete old log entries. This approach works well for applications in a shared environment as you do not need permissions to create SQL jobs, but rather just permission to create/alter a stored procedure. The ELMAH_LogError stored procedure is the stored procedure used by the SQL Server provider for logging errors; it inserts a record into the ELMAH_Error table. Update this table by adding a DELETE statement that deletes all log records older than a certain threshold. For example, the following DELETE statement removes all log entries more than 90 days old.
DELETE FROM [ELMAH_Error] WHERE TimeUtc < DATEDIFF(d, -90, getdate())
Add the above statement after the INSERT statement in the stored procedure. Doing so will cause the error log to be pruned of entries older than 90 days anytime a new error is logged. (I've never used an ELMAH log provider other than the SQL Server provider, so I'm not certain what stored procedures or queries or other things would need to be changed to implement such log trimming using an alternate provider.)
Keep in mind that trimming the error log brings with it a tradeoff: you are removing error log entries that might be important for analysis later in time. If this is the case, if you think you might need to review that error log from more than 90 days in the past, then before deleting records from the error log you should archive them somewhere.
Happy Programming!
|
-
Maryland has a number of geek attractions inside and around its borders. Here’s a sampling: There are two locations to visit. The museum on the National Mall is in the heart of D.C. and features over 20 exhibition galleries that include an Apollo 11 command module, lunar rocks, IMAX theater, and planetarium. For truly colossal exhibits you’ll want to head ~22 miles out of town to the Steven F. Udvar-Hazy Center. Located just off the approach to Dulles airport’s runway 1R, the museum includes the space shuttle Enterprise, and an SR-71 Blackbird. You shouldn’t need any more reasons to go. Nothing says “hard core geek” more than spending time in a museum dedicated to cryptology. The museum is located within electronic eavesdropping range* of the NSA headquarters on a drab stretch of Route 32. But inside you’ll find many compelling exhibits and intriguing devices, like a Jefferson cipher wheel, an Enigma machine, and a Cray Y-MP supercomputer that could hold 32 GB of memory … in 1993. You don’t need a password to get in. It’s a little bit of NASA just outside the D.C. beltway in Greenbelt, MD. Exhibits include a rocket garden, a spherical movie screen, and a sycamore tree grown from a seed that went to the moon and back with Apollo 14 in 1971. Model rocket launching on the first Sunday of every month! The MSC sits diagonally across the water from the National Aquarium in Baltimore’s inner harbor. It was voted as one of the 10 best science centers for families by Parents’ magazine and includes interactive exhibits that range from the cells inside us, to the stars around us. The aquarium on the other side of the harbor is top notch, too, with great food and other sights in between. What’s so geeky about a scenic railroad ride in the mountains? In short: steam power, bridges, tunnels, and turn tables. As a kid I found myself absolutely astounded by the fact that steam (which I thought of then as really hot water), could propel such massive weight. There are also murder mystery trains on the weekends, which is just as geeky as D&D, but without the 20 sided die rolling. The museum is located on the Aberdeen Proving Ground and contains a formidable number of engineering marvels with German, Soviet, Japanese, American, and Italian tanks and artillery pieces. An exhibit both extraordinary and sobering. The museum is relocating to southern Virginia in 2011. * This would be them eavesdropping on you, as I wouldn’t recommend the reverse approach. 
|
-
As the “write less, do more” library, jQuery garners lots of love for its terseness. The terseness, combined with a rich ecosystem of plug-ins, means I can display my OdeToCode twitter feed on a web page using only 10 lines of code (complete with animation and custom loading message)*. $(function() {
$("#getTweets").click(function() {
$("#tweets").getTwitter({
userName: $("#screenname").val(),
numTweets: 10,
loaderText: "Fetching tweets...",
slideIn: true,
showHeading: true,
headingText: "Latest Tweets",
showProfileLink: true
});
return false;
});
});
When writing with jQuery there is a tendency to use nested functions and collapse as many responsibilities as possible into a single piece of code. For many web pages this approach is entirely suitable.We aren’t building a space shuttle - it’s just a web page. The code above is responsible for locating the DOM element for events, hooking up a click event, fetching tweets, and locating the DOM element to display the tweets.
Composite UIs
In more complex pages, and particularly in composite pages that are made up from independent pieces, the above approach tends to become brittle, and encapsulation breaks down as independent pieces try to peek into each other’s private business. It’s easy to fall into black hole of JavaScript code that swallows all who come near. A step away from the black hole would be to extract some of the common, reusable functionality into different pieces.
For example, you can separate the piece that knows about DOM elements … $(function() {
$("#getTweets").click(function() {
getTweets($("#tweets"), $("#screenname").val());
return false;
});
});
… from the piece that knows about Twitter, and include the pieces independently … function getTweets(element, screenname) {
$(element).getTwitter({
userName: screenname,
numTweets: 10,
loaderText: "Loading tweets...",
slideIn: true,
showHeading: true,
headingText: "Latest Tweets",
showProfileLink: true
});
}
Now we have a bit of separation. At this point some of us would be inclined to raise the battle cry of the object oriented programmer, and run off to a workstation to design namespaces, prototypes, constructor functions, properties – blah blah blah**. But we wouldn’t be creating a greater separation between the pieces of code. All we’d really be doing is creating bigger abstractions that are still tied together as closely as they were when they were simple function objects.
Enter The Aggregator
One of the classes I dig in Prism is the EventAggregator. Eventing is pretty much a required approach to managing a composite UI if you want to stay sane. The EventAggregator makes this easy in WPF and SIlverlight, and includes some thread marshalling tricks behind the scenes as a bonus.
Fortunately, you can do something similar in most major JavaScript frameworks, including jQuery. There are jQuery plugins dedicated to event aggregating, but a simple approach would use bind and trigger with custom events, letting the document serve as the aggregator.
Now we can achieve a greater decoupling between the “I need tweets” action … $(function() {
$("#getTweets").click(function() {
$(document).trigger("fetchTweets", [$("#tweets"), $("#screenname").val()]);
return false;
});
});
… and the piece (or pieces) that will respond to such an action… $(document).bind("fetchTweets", function(e, element, screenname) {
$(element).getTwitter({
userName: screenname,
numTweets: 10,
loaderText: "Loading tweets...",
slideIn: true,
showHeading: true,
headingText: "Latest Tweets",
showProfileLink: true
});
});
It’s easy to layer in additional behavior to the “Get Tweets” button click. We could call a web service to save the user’s preferences. We could cache information. We could add some debugging info … $(document).bind("fetchTweets", function(e, element, screenname) {
console.log(screenname);
});
All these things could be done by including separate scripts, and without putting any knowledge of these actions inside the click event handler where the aggregated event begins. Of course, to complete the circle, the code should raise an event when the tweets are retrieved, and let someone else deal with the results.
* Most excellent Twitter plug-in is available from @code_za’s blog.
** I’m not saying that bending prototypes to act like classes is bad, it’s just not the solution to every problem. 
|
-
In ASP.NET MVC, you can use a collection of SelectListItems to help build an HTML <select>. Just watch out for the HTML helper overloads. The question is – what is the prettiest code that can change a list of Products into a collection of SelectListItems? Tonight, you’ll be the judge in this first contest of charm, grace, and readability. Contestant #1 hails from the System.Web.Mvc namespace. It likes pina coladas and string literals, but is turned off by tattoos that look like programming symbols. Let me introduce the SelectList class: var products = GetProducts();
var selectItems = new SelectList(products, "ID", "Name");
Contestant #2 lives in the System.Linq namespace. It likes whips and method chains. Functional programmers call it “map”, but in .NET we call it "Select":
var selectItems = from product in GetProducts()
select new SelectListItem
{
Text = product.Name,
Value = product.ID.ToString()
};
… or (from the backside) …
var selectList = GetProducts().Select(product =>
new SelectListItem
{
Value = product.ID.ToString(),
Text = product.Name
});
Contestant #3 lives in the MvcContrib project. It’s turned on by pointy things and practices yoga for extensibility. Introducing the ToSelectList method:
var selectItems = GetProducts().ToSelectList(product => product.ID,
product => product.Name);
Personally, I like #2. While the name of #3 makes its purpose obvious, it sometimes takes a moment to be 100% clear about what property becomes Text, and what property becomes Value. In #2 the Text and Value assignments are obvious, even though the code is a little longer. Setting the Selected properties with either approach is trivial.
What do you think? 
|
-
I’m in the UK today and tomorrow (on my way back from a trip to India for two days earlier this week), and am giving two tech talks while in town. The first is this evening at a London .NET User Group event. I’ll be presenting Silverlight 3. Unfortunately the event is already over-registered – so if you haven’t registered yet you’ll need to catch it the next time I’m in town. The second talk is tomorrow (Friday) from 1-4pm at the Microsoft facility in Reading and is on ASP.NET MVC. When we first announced it last week it also over-registered quickly. Thankfully my hosts were able to get a larger room this week, though, so another 120 spots became available. You can register to attend the talk for free until 4pm today if you want to attend. Hurry, though, as there are only 43 seats left (down from 57 seats when I first started writing this blog post). Hope to see some of you there, Scott 
|
-
It’s possible to do a lot of work with ASP.NET and not know anything about IIS,
particularly if you work with a large team where IT specialists keep the riff-raff
away from production web applications. Ever since Visual Studio started shipping
its own web server1, many people don’t rely on IIS for day
to day development work (although many of us still do).
For those of you who are just learning how to deploy in IIS, or those of you who
need a refresher, I put together a short and free Pluralsight screen cast on IIS: Web Sites, Applications, and Virtual Directories in IIS
This is one video in a collection of screencasts from Pluralsight.
1) Some people call the web server “Cassini”. Other people call it the “WebDev”
server. Still others call it “the web thingy that sits in my system tray”,
even though Windows doesn’t have a system tray, but whatever. If you worked with the first
release of Visual Studio, you’ll know we’ve come a long way from running as an administrator
with Front Page Extensions installed and the IDE trying to force all of our code
to live underneath inetpub\wwwroot <shudder />.

|
|
|
|