ASP.Net

ASP.Net MVC 2 Released

Trusted By

Welcome Back! I hope you enjoy the content on this site. If you have not done so already, you may want to subscribe to my RSS feed or become a fan of this blog on Facebook. Thanks for visiting!

ASP.NET MVC 2 is now available for Visual Studio 2008 and Visual Web Developer 2008 Express with ASP.NET 3.5. You can download and install it from the following locations:

The final release of Visual Studio 2010 and Visual Web Developer 2010 will have ASP.NET MVC 2 built-in – so you won’t need an additional install in order to use ASP.NET MVC 2 with them.

Some of the new features and capabilities include:

  • New Strongly Typed HTML Helpers
  • Enhanced Model Validation support across both server and client
  • Auto-Scaffold UI Helpers with Template Customization
  • Support for splitting up large applications into “Areas”
  • Asynchronous Controllers support that enables long running tasks in parallel
  • Support for rendering sub-sections of a page/site using Html.RenderAction
  • Lots of new helper functions, utilities, and API enhancements
  • Improved Visual Studio tooling support

For more information, see ASP.NET MVC 2 Released.

5 Most Common Asked Questions When Using .Net RIA Services

From the comments on my previous articles on .Net RIA Services and from the search queries that lead to those articles, a pattern of a recurring set of questions showed up and I am sure that most .Net RIA Services enthusiasts face the same issues.

I will try and address a few of this issues in this post.

Oh, and please subscribe to my RSS Feed if you would like to read more on .Net RIA Services and other cool stuff I write about.

How to Exclude a Property with an Unsupported Type

I am sure this happened to most of you. You have a DomainService and you write a method to return one of your custom types that uses an Unsupported Type in .Net RIA Services. You build your solution and you get the following error.

Service operation named ‘GetUser’ does not conform to the required signature. Both return and parameter types must be an entity type or one of the predefined serializable types.

The error message is actually not that helpful as you tend to first think that there is something wrong with the method signature in the DomainService. But as it happens the issue is with the return type or the type of the parameter of that method.

The solution is really simple, all you have to do is add the ExcludeAttribute available in System.Web.DomainServices. For example in your class you have a reference to a MembershipUser in a property and you want to Exclude it your code would look like this

[Exclude]
public MembershipUser MyUser { get; set; }

 

The exclude attribute Indicates that an entity member should not exist in the code generated client view of the entity, and that the value should never be sent to the client.

How to Consume Services from Different Domains (URIs)

This is a question that came up in the comments of my Hello World .Net RIA Services example.

So the scenario is you have one client Silverlight application but multiple services that you want to consume, these can be on the same server or reside in different datacenters. This scenario can happen in delocalized units in large organizations where the client needs to figure out which server it should query for a specific info.

Luckily the guys behind .Net RIA Services thought about this and offer us a really simple way to achieve it. For each DomainService in our ASP.Net application a DomainContext is generated for the client application.

The generated class has 3 constructors, but the one we are interested in is the one that takes a Uri as a parameter.

/// <summary>
/// Constructor used to specify a data service URI.
/// </summary>
/// <param name="serviceUri">
/// The MyService data service URI.
/// </param>
public MyServiceContext(Uri serviceUri) :
       base(new HttpDomainClient(serviceUri))
{
}

Using this constructor we can specify which Server we want to connect to.

How to Return a String in a DomainService

This does not apply to strings only but for any Supported Type by the framework.

The solution is very simple, even though it took me a few minutes to figure it out. All you have to do is add the ServiceOperationAttribute to your method so that it’s generated in the DomainContext of the client application.

[ServiceOperation]
public string GetMyString()
{
   return "MyString";
}
 

How to Share a Class with the Silverlight Client

Sometimes we write utility classes that we would like available in our Business Tier as well as in our Presentation Tier. To achieve this in .Net RIA Services what we would do is append the .shared.cs suffix to the file that contains the class.

The generator automatically copies the content of that class that would be compiled both at the ASP.Net application as well as at the Silverlight Client level. Here is an excerpt from the .Net RIA Service overview:

This code can be compiled and executed on both the server and the client tiers. It is important to take a moment to consider why this is so. The .NET RIA Services framework automatically creates client proxy classes in the Silverlight project for all entities exposed by the server’s DomainService class. The framework preserves the entities’ namespace, name, and public properties.

When our sample server project compiles, the entity types are actually those generated by our Entity Framework database. However, when this code compiles on the client, these entity types are the generated client proxies.

In this way, the shared application logic is shared at the source level and compiled separately by the server and client projects. This makes it easy to author code once that can be used across tier boundaries.

 

What are all the Attributes Available in the .Net RIA Services Framework

 

Entity Attributes

These are attributes that can be applied to Entities used in your application:

ExcludeAttribute: Indicates that an entity member should not exist in the code generated client view of the entity, and that the value should never be sent to the client.

IncludeAttribute: When applied to an entity association, this attribute indicates that the framework should follow the association when non-null during serialization to send associated objects to the client. This attribute can also be used to specify member projections.

MetadataTypeAttribute: Used for associating a metadata class with the entity class.

Metadata Attributes

The Metadata attributes are used in the Metadata class associated with an entity:

AssociationAttribute: Used to mark an Entity member as an association

ConcurrencyCheckAttribute:This attribute is used to mark the members of a Type that participate in optimistic concurrency checks.

CustomValidationAttribute: Validation attribute that executes a user-supplied method at runtime.

DataTypeAttribute: Allows for clarification of the DataType represented by a given property (such as Password vs URL)

DisplayAttribute: DisplayAttribute is a general-purpose attribute to specify user-visible globalizable strings for types and members. The string properties of this class can be used either as literals or as resource identifiers into a specified ResourceType

DisplayColumnAttribute: Sets the display column, the sort column, and the sort order for when a table is used as a parent table in FK relationships.

DisplayFormatAttribute: Allows overriding various display-related options for a given field. The options have the same meaning as in BoundField.

FilterUIHintAttribute: An attribute used to specify the filtering behavior for a column.

KeyAttribute: Used to mark one or more entity properties that provide the entity’s unique identity

RangeAttribute: Used for specifying a range constraint

RegularExpressionAttribute: Regular expression validation attribute

RequiredAttribute: Validation attribute to indicate that a property field or parameter is required.

StringLengthAttribute: Validation attribute to assert a string property, field or parameter does not exceed a maximum length

TimestampAttribute: This attribute is used to mark a Timestamp member of a Type.

UIHinAttribute: Attribute to provide a hint to the presentation layer about what control it should use.

ValidationAttribute: Base class for all validation attributes.

DomainService Attributes

Note that most of the CRUD operations can be inferred from the name of the method and the is not need to use the attribute.

AuthorizationAttribute: Identifies the permissions required to invoke a DomainOperationEntry.

CustomAttribute: Attribute applied to a DomainService method to indicate that it is a custom method.

DeleteAttribute: Attribute applied to a DomainService method to indicate that it is a delete method.

IgnoreOperationAttribute: Attribute applied to a DomainService method to indicate that code generators should not infer a method as a domain operation.

InsertAttribute: Attribute applied to a DomainService method to indicate that it is an insert method.

MetadataProviderAttribute: Apply this attribute to a DomainService to specify one or more custom TypeDescriptionProvider Types that should be registered for all entity types exposed by the DomainService.

QueryAttribute: Attribute applied to a DomainService method to indicate that it is a query method.

RequiresAuthenticationAttribute: Identifies the authentication requirements needed to invoke a DomainOperationEntry.

RequiresRolesAttribute: Identifies the roles required to invoke a DomainOperationEntry.

ResolveAttribute: Attribute applied to a DomainService method to indicate that it is a resolve method.

ServiceOperationAttribute: Attribute applied to a DomainService method to indicate that it is a service operation.

UpdateAttribute: Attribute applied to a DomainService method to indicate that it is an update method.

Hope this helps.

Hatim

.Net RIA Services Metadata Programming Model

This is the third part of the a multi post series on .Net RIA Services.

First Part - Getting Started with .Net RIA Services

Second Part - .Net RIA Services – Hello World

In this part I will talk about using the .Net RIA Services Metadata Model for data validation and authorization. Unlike the second part of this series this won’t be a tutorial but more of a theoretical article.

We have all suffered when designing business applications to implement data validation and authorization. It’s a dull and meticulous process that bores the hell out of any developer.

Proper data validation should be implemented at two levels, at the UI with ASP.Net validators for example and at the business tier. What if we could write user input validation and data validation code only once in such a way that it’s used both at the UI level and in the business tier, and lets push it further, what if we could write it such that no matter which client (Presentation Layer) we use it will be taken into consideration. Sounds pretty optimistic? Actually it’s not, this is exactly what .Net RIA Services Metadata programming model can do for you.

We would start by defining our Entity class, the Metadata class and then a DomainService to enable client access from the Silverlight application so we can take a look at how the validation Metadata is translated on the client side.

Defining the Entity and the Metadata Class

Let’s take a look at some code. Say you are writing a inventory system and have a product class defined like this:

public class Product
{
    public string Name { get; set; }

    public string SKU { get; set; }

    public double Price { get; set; }
}

 

We  surely want to have some validation when the user inputs this values. So we want:

  • All three properties to be required
  • The SKU to have a length of 8 characters.
  • The Price to be greater than zero
  • Define a Key for the Entity

We would start by creating a Metadata class for our Product class we will call it ProductMetadata.

Metadata classes provide a convenient way to attach metadata to an entity without actually modifying the corresponding members on the entity itself.

The rules for using a metadata class are:

  1. The entity class must be marked with [MetadataType] to name the metadata class
  2. The metadata class must contain only members whose name match members in the entity class.

The metadata class may omit members it does not want to extend, but it may not contain members not in the entity class. The members are required only to match in name, which explains why Name is a property in the Product class but a field in the metadata class.

Metadata members are not required to be of the same type as their corresponding entity member, but it helps readability if they are.

For every member of the entity class that has a matching member in the metadata class, the custom attributes are combined. The metadata class exists only on the server. When code-generation creates the client proxy class for the entity, the custom attributes are combined into the the generated class.

Bellow is the product class with the Metadata class:

[MetadataType(typeof(ProductMetadata))]
public class Product
{
   public string Name { get; set; }

   public string SKU { get; set; }

   public double Price { get; set; }

   internal sealed class ProductMetadata
   {
      public string Name;

      public string SKU;

      public double Price;
   }

}

 

Notice the attribute we added to the Product class that sets which class we would use for the Metadata:

[MetadataType(typeof(ProductMetadata))]
 

Making the Properties Required

To make the properties required all we need to do is add the validation attribute RequiredAttribute available in System.ComponentModel.DataAnnotations. The class should now look like this:

internal sealed class ProductMetadata
{
   [Required]
   public string Name;

   [Required]
   public string SKU;

   [Required]
   public double Price;
}

 

Setting  the SKU Length

We use the StringLengthAttribute also available in System.ComponentModel.DataAnnotations. This attribute is used to assert a field, parameter or property does not exceed a defined length.

[Required]
[StringLength(8,MinimumLength=8)]
public string SKU;

 

Validate the price

We use the RangeAttribute also available in System.ComponentModel.DataAnnotations. This attribute is used for specifying a range constraint.

[Required]
[Range(0, double.MaxValue)]
public double Price;

 

Defining a Key for the Entity

This is pretty simple as well. We can use the SKU as the key for the entity as it should be unique for each product. And for that we use the KeyAttribute which is used to set the unique identifier for an Entity.

[Required]
[StringLength(8,MinimumLength=8)]
[Key]
public string SKU;

Building the Product DataStore

To be able to use our Product class from Silverlight client application we need to create a “fake” DataStore which we would use to retrieve dummy data from.

The store is a simple class which defines a List<T> of products and a getter property to return the list.

public class ProductData
{
    private List<Product> m_products = new List<Product>(new Product[] {
        new Product() { Name="Mouse", SKU="MOU12345", Price=99.00},
        new Product() { Name="Keyboard", SKU="KEY45678", Price=159.00}});

    public IList<Product> Products
    {
        get
        {
            return this.m_products;
        }
    }
}

Creating a DomainService for the Product class

The DomainService class would reference the Product store and have a method that would return the list of products. The goal here as said earlier is not to explain how the domain service works but to create the necessary parts to take a look at how the Metadata attributes are translated in the generated code.

So here is the code for the ProductService:

[EnableClientAccess()]
public class ProductService : DomainService
{
    private ProductData m_productData = new ProductData();

    public IEnumerable<Product> GetProducts()
    {
        return this.m_productData.Products;
    }
}

 

Now we have all the parts needed  so let’s take a look at the generated code.

The Generated Validation Code

When we open the generated cs file in the Silverlight client application, beside the generated method from the DomainService we also find a translated definition of our Product class:

[DataContract(
Namespace="http://schemas.datacontract.org/2004/07/Demo.HelloWorld.Data_Models")]
    public sealed partial class Product : Entity
    {

        private string _name;

        private double _price;

        private string _sku;

        [DataMember()]
        [Required()]
        public string Name
        {
            get
            {
                return this._name;
            }
            set
            {
                if ((this._name != value))
                {
                    this.ValidateProperty("Name", value);
                    this.RaiseDataMemberChanging("Name");
                    this._name = value;
                    this.RaiseDataMemberChanged("Name");
                }
            }
        }

        [DataMember()]
        [Range(((double)(0)), ((double)(1.7976931348623157E+308)))]
        [Required()]
        public double Price
        {
            get
            {
                return this._price;
            }
            set
            {
                if ((this._price != value))
                {
                    this.ValidateProperty("Price", value);
                    this.RaiseDataMemberChanging("Price");
                    this._price = value;
                    this.RaiseDataMemberChanged("Price");
                }
            }
        }

        [DataMember()]
        [Key()]
        [Required()]
        [StringLength(8, MinimumLength=8)]
        public string SKU
        {
            get
            {
                return this._sku;
            }
            set
            {
                if ((this._sku != value))
                {
                    this.ValidateProperty("SKU", value);
                    this.RaiseDataMemberChanging("SKU");
                    this._sku = value;
                    this.RaiseDataMemberChanged("SKU");
                }
            }
        }

        public override object GetIdentity()
        {
            return this._sku;
        }
    }

 

We notice that all our validation and Metadata added is also available on the client side as well as the validation method call:

this.ValidateProperty("Name", value);
 

This call is what makes it work, before the change of the property’s value it’s validated and a validation error is raised if it doesn’t meet the constraints.

I hope that was a helpful description of how get started using the Metadata Model in .Net RIA Services.

Please Subscribe to my RSS Feed to follow this series on the .Net RIA Services.

Oh and if you liked the article please Kick It bellow! :)

kick it on DotNetKicks.com

.Net RIA Service – Hello World

This is the second part of the a multi post series on .Net RIA Services. The first part – Getting Started with .Net RIA Services - was about how to get started, what you need to install and an overview of the platform. If you are new to the platform I recommend reading the overview first.

On this article I will focus on building a simple Hello World application to explain the use of the domain service and the code generation on the client side.

So let’s get to it, we will start by creating our solution and adding our projects. We will first create an ASP.Net Web Application:

image 

We will call our web application Demo.HelloWorld and create the solution at the same time.

The next step is to add a new project to our solution to create the Silverlight client application:

image

Leave everything in the next dialog as it is. It should look like this:

image

One thing that is important is the “link to ASP.NET server project” check box. This tells visual studio and the generator that we want to generate proxy classes for our client.

You can also set this option from the properties page of the Sliverlight client application.

image

Now your  solution should have this structure:

image

Now that we are all setup we can get to the interesting stuff.

The component that allows all the magic  to happen and is the critical step that demonstrates the new features of the .Net RIA Services Framework is the DomainService Class; so let’s take a deeper look at this class.

A DomainService is a class that exposes entities and operations for a specific data domain. It is also where you can add the application logic. You can think of it as the business layer in an n-tier application.

The .NET RIA Services framework contains the plumbing code to make the entities and operations declared in a DomainService class available to other tiers.

We will create our sample DomainService by selecting the server project and choosing Add New Item. Under the Web category is the new Domain Service Class template. We choose to call this new DomainService class HelloWorldService:

image

Next we are presented with another dialog dialog where we can Enable/Disable Client Access. Enabling client access results in having the class tagged with the attribute EnableClientAccess this attribute will tell Visual Studio to generate the proxy class to any linked client.

We can also specify the DataContext or ObjectContext that the domain service will utilize. Since we haven’t defined any we will leave this part to its default value.

image

Our HelloWorldService class should look like this:

namespace Demo.HelloWorld
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.ComponentModel.DataAnnotations;
    using System.Linq;
    using System.Web.Ria;
    using System.Web.Ria.Data;
    using System.Web.DomainServices;

    // TODO: Create methods containing your application logic.
    [EnableClientAccess()]
    public class HelloWorldService : DomainService
    {
    }
}

 

If we compile our solution we will get the following warning:

image

So let’s make the compiler happy and add a method to our service. Our method will be a simple with no arguments and returns a string.

        [ServiceOperation]
        public string SayHello()
        {
            return "Hello RIA World!";
        }

 

Notice the ServiceOperation attribute, methods marked with the [ServiceOperation] attribute will:

  • Generate an event in the DomainContext that will fire when that operation completes

  • Generate a method with the same signature in the DomainContext that will cause the server method to be called immediately but asynchronously

I guess it’s time we talk about the DomainContext. The domain context class is a class that the proxy generated on the client application inherits from and contains the implementation of the plumbing required to invoke the methods on the server.

After building the solution we can take a look at the generated code to call our method in the Silverlight client application.

image

As described above the generated class inherits from DomainContext

public sealed partial class HelloWorldContext : DomainContext
    

 

And here is the implementation of the call to our method. The call is asynchronous and thanks to the .Net RIA Services we don’t need to write any additional code to consume the server side methods from the client app.

public void SayHello()
{
   base.InvokeServiceOperation("SayHello", typeof(string), null, 
                   this.OnSayHelloCompleted, null);
}

 

Now we can try to call our method. Let’s add a TextBlock and a Button to the Silverlight client; to do that open MainPage.xaml and copy/paste the code below.

<UserControl x:Class="Demo.HelloWorld.Client.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Width="400" Height="300">
    <Grid x:Name="LayoutRoot" Background="White">
        <StackPanel Orientation="Vertical">
            <TextBlock Name="HelloTextBlock" Width="150" Height="50" FontSize="15"
                       Margin="5" Foreground="Navy"></TextBlock>
            <Button Name="HelloInvokeButton" Click="HelloInvokeButton_Click" 
                    Width="100" Height="20" Content="Invoke Method"></Button>
         </StackPanel>
    </Grid>
</UserControl>

Add the code bellow to MainPage.xaml.cs

private void HelloInvokeButton_Click(object sender, RoutedEventArgs e)
{
    Demo.HelloWorld.HelloWorldContext context = new HelloWorldContext();

    context.SayHelloCompleted += new EventHandler
                <System.Windows.Ria.Data.InvokeEventArgs>(context_SayHelloCompleted);

    context.SayHello();

}

void context_SayHelloCompleted(object sender, 
                       System.Windows.Ria.Data.InvokeEventArgs e)
{
    HelloTextBlock.Text = (string)e.ReturnValue;
}

 

We added the event handler for the button click and handler for the asynchronous call to our SayHello method.

Now let’s build and test the application:

image

Click on the button to test!

image 

Really cool isn’t it?

Check back soon for the next parts of this series.

Update: Check out the next part about using Metadata Programming in .Net RIA Services

Hope this was helpful.

Hatim

Getting Started with .Net RIA Services

This is a first part of multi-part series, please subscribe to my RSS Feed to follow this series.

I believe that the .Net RIA Services is to ASP.Net what ASP.Net was ASP pages. It really is a great and bold move from Microsoft and represents the future in business oriented applications.

ScaleOut

Announced at MIX 09, .Net RIA Services showed how it’s possible to have a concrete, End-to-End, Application Pattern to build business oriented applications without have to deal with all the fuss and the piping required today to build a Rich Internet application.

You can think of it as RAD for RIA.

RIA Services can pretty much hook up to any back end:

  • Databases through ADO.Net (LINQ to SQL, Entity Framework, …)
  • POCO (Plain Old CLR Objects)
  • Services (Rest, SOAP, …)

An application logic layer called a Domain Service Class is then generated that would handle the CRUD (Create, Retrieve, Update, Delete) and custom operations logic. You can think of this as your business layer in an n-tier architecture.

How it Works Overview – Really Easy

As I would like to make this a multi part post I would just give a brief overview of how to get started and talk in more details of the other features in upcoming posts.

After installing all the required components (see end of post for links) you start with a regular ASP.Net Application Project and a Silverlight client that you link to the ASP.Net project.

image

Now you can create the Domain Service Class that would represent your application logic

CreateDomainClass

Select the DataContexts/ObjectContexts available.

CreateDomainClass1

Now all the methods that you created on the server side in the ASP.Net application would be available through a proxy class that was generated in the Silverlight application as shown in the screen shot bellow.

And can be used as a datasource for a Form, Grid… in the Silverlight application.

image

Pretty cool isn’t it?

.Net RIA services comes with a sleuth of features and that’s just the preview. I am really excited about what we would be able to achieve with this new framework.

What you need

Visual Studio 2008 SP1

Silverlight 3 Beta

.NET RIA Services March ‘09 Preview

Other Interesting Articles on .Net RIA Services

What is .NET RIA Services?

.NET RIA Services: From Vision to Architecture

Mix 09 .Net RIA Services Videos

Building Amazing Business Centric Applications with Microsoft Silverlight 3

.NET RIA Services - Building Data-Driven Applications with Microsoft Silverlight and Microsoft ASP.NET

Please subscribe to my RSS Feed to follow this series.

Hope this was helpful!

Hatim