public class Customer
{
public int Id { get; set; }
...........................
}
public partial class CustomerMap : EntityTypeConfiguration<Customer>
{
public CustomerMap()
{
this.ToTable("Customer");
this.HasKey(c => c.Id);
this.Property(u => u.Username).HasMaxLength(1000);
this.Property(u => u.Email).HasMaxLength(1000);
this.Property(u => u.Password);
this.Property(c => c.AdminComment);
this.Property(c => c.CheckoutAttributes);
this.Property(c => c.GiftCardCouponCodes);
this.Ignore(u => u.PasswordFormat);
this.Ignore(c => c.TaxDisplayType);
this.Ignore(c => c.VatNumberStatus);
this.HasOptional(c => c.Language)
.WithMany()
.HasForeignKey(c => c.LanguageId).WillCascadeOnDelete(false);
this.HasOptional(c => c.Currency)
.WithMany()
.HasForeignKey(c => c.CurrencyId).WillCascadeOnDelete(false);
this.HasMany(c => c.CustomerRoles)
.WithMany()
.Map(m => m.ToTable("Customer_CustomerRole_Mapping"));
this.HasOptional(c => c.Affiliate)
.WithMany()
.HasForeignKey(c => c.AffiliateId);
this.HasMany<Address>(c => c.Addresses)
.WithMany()
.Map(m => m.ToTable("CustomerAddresses"));
this.HasOptional<Address>(c => c.BillingAddress);
this.HasOptional<Address>(c => c.ShippingAddress);
this.HasOptional<Gift>(c => c.SelectedGift);
this.HasMany<Patient>(c => c.Patients)
.WithMany()
.Map(m => m.ToTable("CustomerPatients"));
}
}
public WebCmsDbContext() : base(EngineContext.Current.Resolve<DbSettingModel>().DataConnectionString)
{
//((IObjectContextAdapter) this).ObjectContext.ContextOptions.LazyLoadingEnabled = true;
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//dynamically load all configuration
//System.Type configType = typeof(LanguageMap); //any of your configuration classes here
//var typesToRegister = Assembly.GetAssembly(configType).GetTypes()
var typesToRegister = Assembly.GetExecutingAssembly().GetTypes()
.Where(type => !String.IsNullOrEmpty(type.Namespace))
.Where(type => type.BaseType != null
&& type.BaseType.IsGenericType
&& type.BaseType.GetGenericTypeDefinition() == typeof(EntityTypeConfiguration<>));
foreach (var type in typesToRegister)
{
dynamic configurationInstance = Activator.CreateInstance(type);
modelBuilder.Configurations.Add(configurationInstance);
}
//...or do it manually below. For example,
//modelBuilder.Configurations.Add(new LanguageMap());
base.OnModelCreating(modelBuilder);
//modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
}
automataar DbContext -ruu Entity class nemj bn. EntityTypeConfiguration<> ajiglaarai
...................................
Monday, March 25, 2013
Tuesday, March 19, 2013
Silverlight sample contact page using MVVM
<UserControl x:Class="x.ViewPage.ContactPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.SL5"
xmlns:lib="clr-namespace:PrismEmpire.Lib.Tools"
x:Name="userControl"
mc:Ignorable="d"
d:DesignHeight="400" d:DesignWidth="720">
<UserControl.Resources>
<lib:AIVisibilityConverter x:Key="VisibilityConverter"/>
<Style x:Key="ButtonStyle1" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Duration="0" To="#FF555555" Storyboard.TargetProperty="(Shape.Stroke).(SolidColorBrush.Color)" Storyboard.TargetName="rectangle" d:IsOptimized="True"/>
<ColorAnimation Duration="0" To="#FF444444" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="rectangle" d:IsOptimized="True"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Normal"/>
<VisualState x:Name="Disabled"/>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Rectangle x:Name="rectangle" Fill="#FF333333" Stroke="#FF444444" StrokeThickness="2"/>
<TextBlock HorizontalAlignment="Center" TextWrapping="Wrap" Text="{TemplateBinding Content}" VerticalAlignment="Center" TextAlignment="Center" Foreground="#FF999999" FontSize="{TemplateBinding FontSize}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" DataContext="{Binding Contact, Source={StaticResource Locator}}">
<TextBlock HorizontalAlignment="Center" Height="38" Margin="119,47,111,0" TextWrapping="Wrap" Text="Welcome to Prism Empire, thank you for your interest in our Business Solutions. Please fill in the form below and we will contact you within 24 hours." VerticalAlignment="Top" Width="490" Foreground="#FF999999" FontSize="12"/>
<TextBlock HorizontalAlignment="Center" Height="19" Margin="119,85,380,0" TextWrapping="Wrap" Text="Email: noreply@prismempire.com" VerticalAlignment="Top" Width="221" Foreground="White" FontSize="12"/>
<TextBlock HorizontalAlignment="Left" Height="30" Margin="119,127,0,0" TextWrapping="Wrap" Text="Contact Name" VerticalAlignment="Top" Width="164" Foreground="#FF999999"/>
<TextBlock HorizontalAlignment="Left" Height="28" Margin="119,10,0,0" TextWrapping="Wrap" Text="Contact Us" VerticalAlignment="Top" Width="207" Foreground="#FF999999" FontSize="24"/>
<TextBlock HorizontalAlignment="Left" Height="30" Margin="119,162,0,0" TextWrapping="Wrap" Text="Phone Number" VerticalAlignment="Top" Width="164" Foreground="#FF999999"/>
<TextBlock HorizontalAlignment="Left" Height="30" Margin="119,197,0,0" TextWrapping="Wrap" Text="Email" VerticalAlignment="Top" Width="164" Foreground="#FF999999"/>
<TextBlock HorizontalAlignment="Left" Height="30" Margin="119,232,0,0" TextWrapping="Wrap" Text="Company" VerticalAlignment="Top" Width="164" Foreground="#FF999999"/>
<TextBlock HorizontalAlignment="Left" Height="30" Margin="119,267,0,0" TextWrapping="Wrap" Text="Message" VerticalAlignment="Top" Width="164" Foreground="#FF999999"/>
<TextBox x:Name="contactName" Text="{Binding Model.ContactName, Mode=TwoWay}" HorizontalAlignment="Left" Height="25" Margin="242,123,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="240"/>
<TextBlock Visibility="{Binding IsContactNameValid, Converter={StaticResource VisibilityConverter}, Mode=TwoWay}"
HorizontalAlignment="Left" Height="30" Margin="489,127,0,0" TextWrapping="Wrap" Text="Contact name is empty." VerticalAlignment="Top" Width="164" Foreground="Red"/>
<TextBox x:Name="phoneNumber" Text="{Binding Model.PhoneNumber, Mode=TwoWay}" HorizontalAlignment="Left" Height="25" Margin="242,158,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="240"/>
<TextBox x:Name="email" Text="{Binding Model.Email, Mode=TwoWay}" HorizontalAlignment="Left" Height="25" Margin="242,193,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="240"/>
<TextBox x:Name="companyName" Text="{Binding Model.CompanyName, Mode=TwoWay}" HorizontalAlignment="Left" Height="25" Margin="242,228,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="240"/>
<TextBox x:Name="message" Text="{Binding Model.Message, Mode=TwoWay}" HorizontalAlignment="Left" Height="57" Margin="242,263,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="240"/>
<TextBlock Visibility="{Binding IsEmailValid, Converter={StaticResource VisibilityConverter}, Mode=TwoWay}"
HorizontalAlignment="Left" Height="30" Margin="489,197,0,0" TextWrapping="Wrap" Text="Email format is incorrect." VerticalAlignment="Top" Width="164" Foreground="Red"/>
<Button Content="Send" HorizontalAlignment="Left" Height="25" Margin="397,365,0,0" Style="{StaticResource ButtonStyle1}" VerticalAlignment="Top" Width="85">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<cmd:EventToCommand Command="{Binding SendCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
<Button Content="Clear" HorizontalAlignment="Left" Height="25" Margin="307,365,0,0" Style="{StaticResource ButtonStyle1}" VerticalAlignment="Top" Width="85">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<cmd:EventToCommand
Command="{Binding Contact.ClearCommand, Source={StaticResource Locator}}"
CommandParameter="{Binding ElementName=userControl}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
<TextBlock HorizontalAlignment="Left" Height="30" Margin="242,325,0,0" TextWrapping="Wrap"
Text="{Binding IsSentMail, Mode=TwoWay}" VerticalAlignment="Top" Width="240" Foreground="White"/>
</Grid>
</UserControl>
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.SL5"
xmlns:lib="clr-namespace:PrismEmpire.Lib.Tools"
x:Name="userControl"
mc:Ignorable="d"
d:DesignHeight="400" d:DesignWidth="720">
<UserControl.Resources>
<lib:AIVisibilityConverter x:Key="VisibilityConverter"/>
<Style x:Key="ButtonStyle1" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Duration="0" To="#FF555555" Storyboard.TargetProperty="(Shape.Stroke).(SolidColorBrush.Color)" Storyboard.TargetName="rectangle" d:IsOptimized="True"/>
<ColorAnimation Duration="0" To="#FF444444" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="rectangle" d:IsOptimized="True"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Normal"/>
<VisualState x:Name="Disabled"/>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Rectangle x:Name="rectangle" Fill="#FF333333" Stroke="#FF444444" StrokeThickness="2"/>
<TextBlock HorizontalAlignment="Center" TextWrapping="Wrap" Text="{TemplateBinding Content}" VerticalAlignment="Center" TextAlignment="Center" Foreground="#FF999999" FontSize="{TemplateBinding FontSize}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" DataContext="{Binding Contact, Source={StaticResource Locator}}">
<TextBlock HorizontalAlignment="Center" Height="38" Margin="119,47,111,0" TextWrapping="Wrap" Text="Welcome to Prism Empire, thank you for your interest in our Business Solutions. Please fill in the form below and we will contact you within 24 hours." VerticalAlignment="Top" Width="490" Foreground="#FF999999" FontSize="12"/>
<TextBlock HorizontalAlignment="Center" Height="19" Margin="119,85,380,0" TextWrapping="Wrap" Text="Email: noreply@prismempire.com" VerticalAlignment="Top" Width="221" Foreground="White" FontSize="12"/>
<TextBlock HorizontalAlignment="Left" Height="30" Margin="119,127,0,0" TextWrapping="Wrap" Text="Contact Name" VerticalAlignment="Top" Width="164" Foreground="#FF999999"/>
<TextBlock HorizontalAlignment="Left" Height="28" Margin="119,10,0,0" TextWrapping="Wrap" Text="Contact Us" VerticalAlignment="Top" Width="207" Foreground="#FF999999" FontSize="24"/>
<TextBlock HorizontalAlignment="Left" Height="30" Margin="119,162,0,0" TextWrapping="Wrap" Text="Phone Number" VerticalAlignment="Top" Width="164" Foreground="#FF999999"/>
<TextBlock HorizontalAlignment="Left" Height="30" Margin="119,197,0,0" TextWrapping="Wrap" Text="Email" VerticalAlignment="Top" Width="164" Foreground="#FF999999"/>
<TextBlock HorizontalAlignment="Left" Height="30" Margin="119,232,0,0" TextWrapping="Wrap" Text="Company" VerticalAlignment="Top" Width="164" Foreground="#FF999999"/>
<TextBlock HorizontalAlignment="Left" Height="30" Margin="119,267,0,0" TextWrapping="Wrap" Text="Message" VerticalAlignment="Top" Width="164" Foreground="#FF999999"/>
<TextBox x:Name="contactName" Text="{Binding Model.ContactName, Mode=TwoWay}" HorizontalAlignment="Left" Height="25" Margin="242,123,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="240"/>
<TextBlock Visibility="{Binding IsContactNameValid, Converter={StaticResource VisibilityConverter}, Mode=TwoWay}"
HorizontalAlignment="Left" Height="30" Margin="489,127,0,0" TextWrapping="Wrap" Text="Contact name is empty." VerticalAlignment="Top" Width="164" Foreground="Red"/>
<TextBox x:Name="phoneNumber" Text="{Binding Model.PhoneNumber, Mode=TwoWay}" HorizontalAlignment="Left" Height="25" Margin="242,158,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="240"/>
<TextBox x:Name="email" Text="{Binding Model.Email, Mode=TwoWay}" HorizontalAlignment="Left" Height="25" Margin="242,193,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="240"/>
<TextBox x:Name="companyName" Text="{Binding Model.CompanyName, Mode=TwoWay}" HorizontalAlignment="Left" Height="25" Margin="242,228,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="240"/>
<TextBox x:Name="message" Text="{Binding Model.Message, Mode=TwoWay}" HorizontalAlignment="Left" Height="57" Margin="242,263,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="240"/>
<TextBlock Visibility="{Binding IsEmailValid, Converter={StaticResource VisibilityConverter}, Mode=TwoWay}"
HorizontalAlignment="Left" Height="30" Margin="489,197,0,0" TextWrapping="Wrap" Text="Email format is incorrect." VerticalAlignment="Top" Width="164" Foreground="Red"/>
<Button Content="Send" HorizontalAlignment="Left" Height="25" Margin="397,365,0,0" Style="{StaticResource ButtonStyle1}" VerticalAlignment="Top" Width="85">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<cmd:EventToCommand Command="{Binding SendCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
<Button Content="Clear" HorizontalAlignment="Left" Height="25" Margin="307,365,0,0" Style="{StaticResource ButtonStyle1}" VerticalAlignment="Top" Width="85">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<cmd:EventToCommand
Command="{Binding Contact.ClearCommand, Source={StaticResource Locator}}"
CommandParameter="{Binding ElementName=userControl}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
<TextBlock HorizontalAlignment="Left" Height="30" Margin="242,325,0,0" TextWrapping="Wrap"
Text="{Binding IsSentMail, Mode=TwoWay}" VerticalAlignment="Top" Width="240" Foreground="White"/>
</Grid>
</UserControl>
Sunday, March 17, 2013
create database script from entity framework dbcontext
part 1
To set the auto drop and create you would do something like this...
To set the auto drop and create you would do something like this...
public class MyDbContext : DbContext
{
public IDbSet<Foo> Foos { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
Database.SetInitializer(new MyDbContextInitializer());
base.OnModelCreating(modelBuilder);
}
}
public class MyDbContextInitializer : DropCreateDatabaseIfModelChanges<MyDbContext>
{
protected override void Seed(MyDbContext dbContext)
{
// seed data
base.Seed(dbContext);
}
}
part 2
You can create the tables yourself - the easiest way is:
IObjectContextAdapter adapter = (IObjectContextAdapter)context;
string script = adapter.ObjectContext.CreateDatabaseScript();
context.Database.ExecuteSqlCommand(script);
Where context is my EF 4.1 database context. Prior to this code I
drop all the tables (from the last time I created the db), and after
this I seed it with data.part 3
You need to add this to your Application_Start()
part 4
Database.SetInitializer(new MyDbContextContextInitializer());
var context = new MyDbContextContext();
context.Database.Initialize(true);
The last line forces the DB to createdpart 4
Better: add the initializer to the static constructor, like this:
public class MyDbContext : DbContext
{
static MyDbContext()
{
Database.SetInitializer(new MyDbContextContextInitializer());
}
}
Sample Validating Controls in Silverlight
Validating Controls in Silverlight
If ever you have done validation of form controls in ASP.NET or Desktop applications then validating controls in Silverlight will be easy to get to grips with. Unfortunately there are no controls in Silverlight that perform validation, maybe Microsoft will release some at some point but for now we have a few tips for validating and a simple example Registration Form with basic validation.
<UserControl x:Class="SilverlightApplication1.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:liquid="clr-namespace:Liquid;assembly=Liquid"
Width="400" Height="300">
<Canvas>
<Rectangle Width="330" Height="170" RadiusX="7" RadiusY="7" Fill="#44888888" />
<Rectangle Canvas.Left="2" Canvas.Top="2" Width="326" Height="166" RadiusX="5" RadiusY="5" StrokeThickness="2" Stroke="#888888">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="#ffdfdfdf" Offset="0.0" />
<GradientStop Color="#fff8f8f8" Offset="0.7" />
<GradientStop Color="#ffeeeeee" Offset="1.0" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Rectangle Canvas.Left="5" Canvas.Top="5" Width="320" Height="21" StrokeThickness="0.5" Stroke="#7A8295" RadiusX="3" RadiusY="3">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="#626C88" Offset="0.0" />
<GradientStop Color="#393F4D" Offset="0.5" />
<GradientStop Color="#151516" Offset="0.5" />
<GradientStop Color="#3C476F" Offset="1.0" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<TextBlock Text="Username:" Canvas.Left="10" Canvas.Top="35" />
<TextBox x:Name="newUsername" Canvas.Left="120" Canvas.Top="32" Width="200" TabIndex="0" />
<TextBlock Text="Email:" Canvas.Left="10" Canvas.Top="65" />
<TextBox x:Name="newEmail" Canvas.Left="120" Canvas.Top="62" Width="200" TabIndex="1" />
<TextBlock Text="Password:" Canvas.Left="10" Canvas.Top="95" />
<TextBox x:Name="newPassword" Canvas.Left="120" Canvas.Top="92" Width="200" TabIndex="2" />
<HyperlinkButton x:Name="registerHelp" Canvas.Left="10" Canvas.Top="146" NavigateUri="help.aspx" Content="Problems Registering?" />
<TextBlock x:Name="registerStatus" Canvas.Left="10" Canvas.Top="121" Foreground="Red" FontSize="10" FontWeight="Bold" />
<Button Canvas.Left="200" Canvas.Top="133" Width="50" Content="Cancel" Click="RegisterCancel_Click" />
<Button x:Name="registerRegister" Canvas.Left="260" Canvas.Top="133" Width="60" Content="Register" Click="Register_Click" />
</Canvas>
</UserControl>
code behind
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace SilverlightApplication1
{
public partial class Page : UserControl
{
public Page()
{
InitializeComponent();
}
private void RegisterCancel_Click(object sender, RoutedEventArgs e)
{
// Registration has been cancelled. Handle this here
}
private void Register_Click(object sender, RoutedEventArgs e)
{
// Clear the status text
registerStatus.Text = "";
if (newPassword.Text.Length == 0)
{
// No password entered
registerStatus.Text = "Enter a password.";
newPassword.Focus();
}
if (newEmail.Text.Length == 0)
{
// No email address entered
registerStatus.Text = "Enter an email.";
newEmail.Focus();
}
else if (!Regex.IsMatch(newEmail.Text, @"^[a-zA-Z][\w\.-]*[a-zA-Z0-9]@[a-zA-Z0-9][\w\.-]*[a-zA-Z0-9]\.[a-zA-Z][a-zA-Z\.]*[a-zA-Z]$"))
{
// An invalid email format was entered
registerStatus.Text = "Enter a valid email.";
newEmail.Select(0, newEmail.Text.Length);
newEmail.Focus();
}
if (newUsername.Text.Length == 0)
{
// No username was entered
registerStatus.Text = "Enter a username.";
newUsername.Focus();
}
// Return if the status text is not empty
if (registerStatus.Text.Length > 0)
{
return;
}
// All done, the 3 fields have been validated
// Do your registration processing here....
}
}
}
Thursday, March 14, 2013
Getting up and running with Autofac on ASP.NET
The basic pattern for integrating Autofac into your application is:
For our sample app, we'll define a class that writes the current date out. However, we don't want it tied to the Console because we want to be able to test the class later or use it in a place where the console isn't available.
We'll also go as far as allowing the mechanism writing the date to be abstracted, so if we want to, later, swap in a version that writes tomorrow's date, it'll be a snap.
We'll do something like this:
The easiest way to do this is through NuGet. The "Autofac" package has all the core functionality you'll need.
In simple terms, think about a .NET type that implements an interface, like this:
In Autofac, you'd register that with a ContainerBuilder something like this:
We also need to store the container so it can be used to resolve types later.
The container itself is a lifetime scope, and you can technically just resolve things right from the container. It is not recommended to resolve from the container directly, however.
When you resolve a component, depending on the instance scope you define, a new instance of the object gets created. (Resolving a component is roughly equivalent to calling "new" to instantiate a class. That's really, really oversimplifying it, but from an analogy perspective it's fine.) Some components may need to be disposed (like they implement IDisposable) - Autofac can handle disposing those components for you when the lifetime scope is disposed.
However, the container lives for the lifetime of your application. If you resolve a lot of stuff directly from the container, you may end up with a lot of things hanging around waiting to be disposed. That's not good (and you may see a "memory leak" doing that).
Instead, create a child lifetime scope from the container and resolve from that. When you're done resolving components, dispose of the child scope and everything gets cleaned up for you.
(When you're working with the Autofac integration libraries, this child scope creation is largely done for you so you don't have to think about it.)
For our sample app, we'll implement the "WriteDate" method to get the writer from a scope and dispose of the scope when we're done.
Note: generally speaking, service location is largely considered an anti-pattern. That is, manually creating scopes everywhere and sprinkling use of the container through your code is not necessarily the best way to go. Using the Autofac integration libraries you usually won't have to do what we did in the sample app above. Instead, things get resolved from a central, "top level" location in the application and manual resolution is rare. Of course, how you design your app is up to you.
- Structure your app with inversion of control (IoC) in mind.
- Add Autofac references.
- At application startup...
- Create a ContainerBuilder.
- Register components.
- Build the container and store it for later use.
- During application execution...
- Create a lifetime scope from the container.
- Use the lifetime scope to resolve instances of the components.
- Structuring the Application
- Add Autofac References
- Application Startup
- Application Execution
- Going Further
- Need Help?
- Building from Source
Structuring the Application
The idea behind inversion of control is that, rather than tie the classes in your application together and let classes "new up" their dependencies, you switch it around so dependencies are instead passed in during class construction. Martin Fowler has an excellent article explaining dependency injection/inversion of control if you want more on that.For our sample app, we'll define a class that writes the current date out. However, we don't want it tied to the Console because we want to be able to test the class later or use it in a place where the console isn't available.
We'll also go as far as allowing the mechanism writing the date to be abstracted, so if we want to, later, swap in a version that writes tomorrow's date, it'll be a snap.
We'll do something like this:
using System; namespace DemoApp { // This interface helps decouple the concept of // "writing output" from the Console class. We // don't really "care" how the Write operation // happens, just that we can write. public interface IOutput { void Write(string content); } // This implementation of the IOutput interface // is actually how we write to the Console. Technically // we could also implement IOutput to write to Debug // or Trace... or anywhere else. public class ConsoleOutput : IOutput { public void Write(string content) { Console.WriteLine(content); } } // This interface decouples the notion of writing // a date from the actual mechanism that performs // the writing. Like with IOutput, the process // is abstracted behind an interface. public interface IDateWriter { void WriteDate(); } // This TodayWriter is where it all comes together. // Notice it takes a constructor parameter of type // IOutput - that lets the writer write to anywhere // based on the implementation. Further, it implements // WriteDate such that today's date is written out; // you could have one that writes in a different format // or a different date. public class TodayWriter : IDateWriter { private IOutput _output; public TodayWriter(IOutput output) { this._output = output; } public void WriteDate() { this._output.Write(DateTime.Today.ToShortDateString()); } } }Now that we have a reasonably structured (if contrived) set of dependencies, let's get Autofac in the mix!
Add Autofac References
The first step is to add Autofac references to your project. For this example, we're only using core Autofac. Other application types may use additional Autofac integration libraries.The easiest way to do this is through NuGet. The "Autofac" package has all the core functionality you'll need.
Application Startup
At application startup, you need to create a ContainerBuilder and register your components with it. A component is an expression, .NET type, or other bit of code that exposes one or more services and can take in other dependencies.In simple terms, think about a .NET type that implements an interface, like this:
public class SomeType : IService { }You could address that type in one of two ways:
- As the type itself, SomeType
- As the interface, an IService
In Autofac, you'd register that with a ContainerBuilder something like this:
// Create your builder. var builder = new ContainerBuilder(); // Usually you're only interested in exposing the type // via its interface: builder.RegisterType<SomeType>().As<IService>(); // However, if you want BOTH services (not as common) // you can say so: builder.RegisterType<SomeType>().AsSelf().As<IService>();For our sample app, we need to register all of our components (classes) and expose their services (interfaces) so things can get wired up nicely.
We also need to store the container so it can be used to resolve types later.
using System; using Autofac; namespace DemoApp { public class Program { private static IContainer Container { get; set; } static void Main(string[] args) { var builder = new ContainerBuilder(); builder.RegisterType<ConsoleOutput>().As<IOutput>(); builder.RegisterType<TodayWriter>().As<IDateWriter>(); Container = builder.Build(); // The WriteDate method is where we'll make use // of our dependency injection. We'll define that // in a bit. WriteDate(); } } }Now we have a container with all of the components registered and they're exposing the proper services. Let's make use of it.
Application Execution
During application execution, you'll need to make use of the components you registered. You do this by resolving them from a lifetime scope.The container itself is a lifetime scope, and you can technically just resolve things right from the container. It is not recommended to resolve from the container directly, however.
When you resolve a component, depending on the instance scope you define, a new instance of the object gets created. (Resolving a component is roughly equivalent to calling "new" to instantiate a class. That's really, really oversimplifying it, but from an analogy perspective it's fine.) Some components may need to be disposed (like they implement IDisposable) - Autofac can handle disposing those components for you when the lifetime scope is disposed.
However, the container lives for the lifetime of your application. If you resolve a lot of stuff directly from the container, you may end up with a lot of things hanging around waiting to be disposed. That's not good (and you may see a "memory leak" doing that).
Instead, create a child lifetime scope from the container and resolve from that. When you're done resolving components, dispose of the child scope and everything gets cleaned up for you.
(When you're working with the Autofac integration libraries, this child scope creation is largely done for you so you don't have to think about it.)
For our sample app, we'll implement the "WriteDate" method to get the writer from a scope and dispose of the scope when we're done.
namespace DemoApp { public class Program { private static IContainer Container { get; set; } static void Main(string[] args) { // ...the stuff you saw earlier... } public static void WriteDate() { // Create the scope, resolve your IDateWriter, // use it, then dispose of the scope. using (var scope = Container.BeginLifetimeScope()) { var writer = scope.Resolve<IDateWriter>(); writer.WriteDate(); } } } }Now when you run your program...
- The "WriteDate" method asks Autofac for an IDateWriter.
- Autofac sees that IDateWriter maps to TodayWriter so starts creating a TodayWriter.
- Autofac sees that the TodayWriter needs an IOutput in its constructor.
- Autofac sees that IOutput maps to ConsoleOutput so creates a new ConsoleOutput instance.
- Autofac uses the new ConsoleOutput instance to finish constructing the TodayWriter.
- Autofac returns the fully-constructed TodayWriter for "WriteDate" to consume.
Note: generally speaking, service location is largely considered an anti-pattern. That is, manually creating scopes everywhere and sprinkling use of the container through your code is not necessarily the best way to go. Using the Autofac integration libraries you usually won't have to do what we did in the sample app above. Instead, things get resolved from a central, "top level" location in the application and manual resolution is rare. Of course, how you design your app is up to you.
Going Further
The sample app gives you an idea of how to use Autofac, but there's a lot more you can do.- Check out the list of integration libraries and available NuGet packages to see how to integrate Autofac with your application.
- Learn about the other ways to register components that add flexibility.
- Learn about Autofac modules and the XML configuration mechanism that allow you to better manage your component registrations.
Need Help?
- You can ask questions on StackOverflow.
- You can participate in the Autofac Google Group.
- There's an introductory Autofac tutorial on CodeProject.
- Some companies offer CommercialSupport for Autofac.
Building from Source
The source code along with Visual Studio project files is available here. Build instructions are in a README in the root of the code, and more information about the project is in the ContributionGuidelines.Getting started using Silverlight 4 in an ASP.NET MVC 3 application and accessing data with JSON
ASP.NET MVC is such a great platform for web applications because it
makes it so easy to tackle many different integration challenges. You
need to add a Silverlight application to your web site and send it some
JSON data to work with? No sweat. Stumped on where to start? Well, you
are in the right place. Let's make it happen.
In honor of Mix 11 kicking off tomorrow, we will imagine that we are tasked with the need to build a web application that renders a list of MIX 11 sessions and allows the video of each session to be viewed in a browser (of course we don't really need to build such a solution because the live.visitmix.com site already provides that content for us...but, for the sake of being hypothetical). What a perfect reason to use Silverlight in a MVC 3 web application! We will work through rendering a Silverlight application in an MVC 3 view and populate it with a list of MIX 11 session names delivered in JSON from our MVC application. We will not be addressing how to render video in Silverlight in this post though, so if you want to take the Silverlight portion further you may want to check out www.iwantmysilverlight.com (is anyone actually rockin' that domain name?).
As always, we begin with a blank ASP.NET MVC 3 Web Application project (named Website) using an Empty project template and target the Razor view engine. Once the solution is created with the MVC project we will add a new Silverlight Application project to the solution.
To start this post I didn't have the Silverlight Developer Tools installed on my workstation running Visual Studio 2010 (Service Pack 1), so I encountered the following dialog upon clicking OK from the add project dialog:
Clicking on the link in this dialog opened up a browser and downloaded the installer. After running the installer, restarting Visual Studio 2010, and attempting to add the new Silverlight Application project a second time I found success. The Silverlight Application project prompts you with an options dialog:
I unchecked the options for "Add a test page that references the application" and "Enable Silverlight debugging (disables javascript debugging)" and clicked OK. Once the Silverlight Application project was added my solution tree looked like so:
With the projects in place we are ready to start adding some code. First up, we need to add a controller and a view that will render a page with our Silverlight application on it. Lets add a good old
I clicked No...nothing broke or melted. The page showed up with our h1 tag screaming at us in huge bold font. Now lets see about getting our Silverlight in that view. The SilverlightApplication project comes pre-loaded with a
The default content for the
Now lets get this puppy running in our view. Guess what! By adding the SilverlightApplication to our solution after we added the ASP.NET MVC 3 Web Application we were presented with the "Host the Silverlight application in a new or existing Web site in the solution" option pre-checked and our project named Website pre-selected in the drop down. Since we left that option checked and the Website project selected, when we did a build of our Website application (the F5 we did earlier to preview it) the
We can add an
So we have some Silverlight running in an ASP.NET MVC 3 web application. Coolio! Now lets see what we can do to populate some data in that Silverlight. We will create a new action method in our
Lets take a look at the code in the file as a whole and then we will go over the parts.
And voilĂ , we have a starting point for an integration between ASP.NET MVC 3 and a Silverlight 4 application. The rest is easy right? Simply build a robust Silverlight application solution and update the MVC application to return more complex JSON data. Knock that out in a day or two? I think I'll spend the next day or two sitting at home watching the Mix 11 session online and toss some sadfaces out as I watch all the Twitter chatter from all of those out in Vegas having fun instead. Oh, and answer reader comments of course!
In honor of Mix 11 kicking off tomorrow, we will imagine that we are tasked with the need to build a web application that renders a list of MIX 11 sessions and allows the video of each session to be viewed in a browser (of course we don't really need to build such a solution because the live.visitmix.com site already provides that content for us...but, for the sake of being hypothetical). What a perfect reason to use Silverlight in a MVC 3 web application! We will work through rendering a Silverlight application in an MVC 3 view and populate it with a list of MIX 11 session names delivered in JSON from our MVC application. We will not be addressing how to render video in Silverlight in this post though, so if you want to take the Silverlight portion further you may want to check out www.iwantmysilverlight.com (is anyone actually rockin' that domain name?).
As always, we begin with a blank ASP.NET MVC 3 Web Application project (named Website) using an Empty project template and target the Razor view engine. Once the solution is created with the MVC project we will add a new Silverlight Application project to the solution.
To start this post I didn't have the Silverlight Developer Tools installed on my workstation running Visual Studio 2010 (Service Pack 1), so I encountered the following dialog upon clicking OK from the add project dialog:
Clicking on the link in this dialog opened up a browser and downloaded the installer. After running the installer, restarting Visual Studio 2010, and attempting to add the new Silverlight Application project a second time I found success. The Silverlight Application project prompts you with an options dialog:
I unchecked the options for "Add a test page that references the application" and "Enable Silverlight debugging (disables javascript debugging)" and clicked OK. Once the Silverlight Application project was added my solution tree looked like so:
With the projects in place we are ready to start adding some code. First up, we need to add a controller and a view that will render a page with our Silverlight application on it. Lets add a good old
HomeController
with a Index
action method. Our HomeController.cs
file will contain:using System.Web.Mvc;
namespace Website.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
}
}
Our Views/Home/Index.cshtml
file will contain: @{
ViewBag.Title = "Index";
}
<h1>Our Silverlight application demo</h1>
If we do a quick F5 to check out our page we are presented with the following dialog: I clicked No...nothing broke or melted. The page showed up with our h1 tag screaming at us in huge bold font. Now lets see about getting our Silverlight in that view. The SilverlightApplication project comes pre-loaded with a
MainPage.xaml
file. If we open that file in Visual Studio 2010 it will give us a
split window with a Design view at the top and a XAML view at the
bottom. From here we can use the Toolbox window to add some UX stuff. If
you don't have this displayed because you build rad ASP.NET MVC web
applications without that crazy design view stuff or you recently read
Scott Hanselman's blog post on how to Simplify your Visual Studio 2010 Toolbar and Free Your Mind
and turned off everything under the sun then you can get it back by
hitting Ctrl+Alt+X or navigating to View -> Toolbox from the main
menu.The default content for the
MainPage.xaml
file looks like: <UserControl x:Class="SilverlightApplication.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<Grid x:Name="LayoutRoot" Background="White">
</Grid>
</UserControl>
We will drag and drop a TextBlock
and set the Text
attribute to "Session Videos". This will add the following XAML tag to the <Grid>
tag: <TextBlock Height="23" HorizontalAlignment="Left" Margin="12,12,0,0"
Name="textBlock1" Text="Session Videos" VerticalAlignment="Top" />
Our MainPage.xaml
file will end up looking like so: <UserControl x:Class="SilverlightApplication.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<Grid x:Name="LayoutRoot" Background="White">
<TextBlock Height="23" HorizontalAlignment="Left" Margin="12,12,0,0"
Name="textBlock1" Text="Session Videos" VerticalAlignment="Top" />
</Grid>
</UserControl>
We can preview this by right clicking on the SilverlightApplication
project in the Solution Explorer and selecting "View in Browser" (or
hitting Ctrl+Shift+W). With our browser open we can see our Silverlight
running, displaying the "Session Videos" text. If we right click on the
window content we get the "Silverlight" context menu: Now lets get this puppy running in our view. Guess what! By adding the SilverlightApplication to our solution after we added the ASP.NET MVC 3 Web Application we were presented with the "Host the Silverlight application in a new or existing Web site in the solution" option pre-checked and our project named Website pre-selected in the drop down. Since we left that option checked and the Website project selected, when we did a build of our Website application (the F5 we did earlier to preview it) the
SilverlightApplication.xap
file was created and deployed to a ClientBin
directory in our MVC project. We can add an
<object>
tag to our Index.cshtml
view file to render our Silverlight application within the view. The code for our view file will be: @{
ViewBag.Title = "Index";
}
<h1>Our Silverlight application demo</h1>
<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="400" height="300">
<param name="source" value="ClientBin/SilverlightApplication.xap"/>
<param name="background" value="red" />
<param name="minRuntimeVersion" value="4.0.60129.0" />
<param name="autoUpgrade" value="true" />
<a href="http://www.microsoft.com/getsilverlight/get-started/install/" style="text-decoration:none">
<img src="http://go.microsoft.com/fwlink/?LinkId=161376"
alt="Get Microsoft Silverlight" style="border-style:none"/>
</a>
</object>
If we do another F5 we will see our page with our Silverlight application included. So we have some Silverlight running in an ASP.NET MVC 3 web application. Coolio! Now lets see what we can do to populate some data in that Silverlight. We will create a new action method in our
HomeController.cs
file named SessionVideoList
that will return a JsonResult
that will contain a list of session names we can use in our Silverlight application. We can create a List<string>
of some session names and return it as a Json
object. Our updated controller code: using System.Collections.Generic;
using System.Web.Mvc;
namespace Website.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
public JsonResult SessionVideoList()
{
var sessionVideos = new List<string> { "Keynote", "Silverlight Boot Camp",
"Fun with ASP.NET MVC 3 and MEF", "ASP.NET MVC 3 @:The Time is Now" };
return Json(sessionVideos, JsonRequestBehavior.AllowGet);
}
}
}
We also need to add a route to our route table to be able to call this action method. An update to our Global.asax.cs
file will look like so: using System.Web.Mvc;
using System.Web.Routing;
namespace Website
{
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"SessionVideoList",
"SessionVideoList",
new { controller = "Home", action = "SessionVideoList" }
);
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
}
}
Our MVC application is set up to provide data for our Silverlight
application to consume. Our final step involves adding the code to our
Silverlight application to hit our MVC route and process the data
returned. To keep it simple, we will modify our MainPage.xaml
file to enlarge the TextBlock element so that it fills the Silverlight
application and use that to render our list of session names. We can add
a Width
attribute and change the existing Height
attribute on our <TextBlock>
tag:<TextBlock Height="276" HorizontalAlignment="Left" Margin="12,12,0,0"
Name="textBlock1" Text="Session Videos" VerticalAlignment="Top" Width="376" />
This will ensure that the rendering of our TextBlock
will be big enough to display a handful of lines of text. From here we need to open up our MainPage.xaml.cs
file and add some code to call our MVC action url and process the response stream content. In the constructor for MainPage
we will add an instantiation of a Uri
object, a WebClient
object, and do an async read of the Uri
object with the WebClient
object. We will also add a private method named openReadCompleted
that we will add to the WebClient.OpenReadCompleted
event handler. This method will handle processing the JSON data from the response stream and populating our TextBlock
element. We are going to use System.Json
to process the JSON data which requires us to add a reference to the .NET assembly in our SilverlightApplication project. Lets take a look at the code in the file as a whole and then we will go over the parts.
using System;
using System.Json;
using System.Net;
namespace SilverlightApplication
{
public partial class MainPage
{
public MainPage()
{
InitializeComponent();
var serviceUri = new Uri("/SessionVideoList", UriKind.Relative);
var webClient = new WebClient();
webClient.OpenReadCompleted += openReadCompleted;
webClient.OpenReadAsync(serviceUri);
}
private void openReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
if (e.Error != null) return;
var sessions = (JsonArray)JsonValue.Load(e.Result);
foreach (string sessionName in sessions)
{
this.textBlock1.Text += string.Format("{0}{1}", Environment.NewLine, sessionName);
}
}
}
}
In the MainPage
constructor we instantiate a new Uri
object. We pass in a relative uri string that represents the route to our action method. We need to include the UriKind
argument (value of UriKind.Relative
)
in this constructor in order for our Silverlight application to
correctly resolve the path when rendered in our MVC application. Then we
instantiate our WebClient
, add the event handler, and do our asynchronous read. public MainPage()
{
InitializeComponent();
var serviceUri = new Uri("/SessionVideoList", UriKind.Relative);
var webClient = new WebClient();
webClient.OpenReadCompleted += openReadCompleted;
webClient.OpenReadAsync(serviceUri);
}
In our openReadCompleted
method we do a simple check for errors and return without taking any action if we encounter an error. From there we use the JsonValue.Load
method to deserialize the response stream data that is stored in the OpenReadCompletedEventArgs.Result
property and cast it to a JsonArray
object. This is based on knowing the structure of the JSON objects we
are dealing with...there are other JSON object types that can be used
here. More info can be found on MSDN. Finally, we iterate through the JsonArray
object and add the session name to a new line in our TextBlock element.private void openReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
if (e.Error != null) return;
var sessions = (JsonArray)JsonValue.Load(e.Result);
foreach (string sessionName in sessions)
{
this.textBlock1.Text += string.Format("{0}{1}", Environment.NewLine, sessionName);
}
}
If we go back to our MVC project and do an F5 we will see our
Silverlight application rendered in our page and populated with the JSON
data from our SessionVideoList
action method. And voilĂ , we have a starting point for an integration between ASP.NET MVC 3 and a Silverlight 4 application. The rest is easy right? Simply build a robust Silverlight application solution and update the MVC application to return more complex JSON data. Knock that out in a day or two? I think I'll spend the next day or two sitting at home watching the Mix 11 session online and toss some sadfaces out as I watch all the Twitter chatter from all of those out in Vegas having fun instead. Oh, and answer reader comments of course!
Subscribe to:
Posts (Atom)