I want to use interceptor in my application in order to do logging.
Of course I could register each type with interceptor like this:
container.AddNewExtension<Interception>();
container.RegisterType<ITenantStore, TenantStore>(
new Interceptor<InterfaceInterceptor>(),
new InterceptionBehavior<LoggingInterceptionBehavior>());
but since I have a lot of types I was wondering if there's a cleaner way to do this for all my classes?
Here's a method that will enable interception on all types that have already been registered. So call this after your registrations are complete. Then you can use Policy Injection to hook up the interceptors you want to use.
public static class UnityContainerInterceptionExtensions
{
public static IUnityContainer EnableInterceptionForAllRegisteredTypes
(this IUnityContainer unityContainer)
{
unityContainer
.Registrations
.ForEach(r => unityContainer.EnableInterception(r.RegisteredType, r.Name));
return unityContainer;
}
public static IUnityContainer EnableInterception<T>
(this IUnityContainer unityContainer, string name = null)
{
return unityContainer.EnableInterception(typeof (T), name);
}
public static IUnityContainer EnableInterception
(this IUnityContainer unityContainer, Type registrationType, string name = null)
{
// Don't allow interception of unity types
if (registrationType.Namespace.StartsWith(typeof(IUnityContainer).Namespace))
return unityContainer;
// Don't allow interception on the intercepting call handlers
if (typeof (ICallHandler).IsAssignableFrom(registrationType))
return unityContainer;
var interception = unityContainer.Configure<Interception>();
var interfaceInterceptor = new InterfaceInterceptor();
if (interfaceInterceptor.CanIntercept(registrationType))
{
interception
.SetInterceptorFor(registrationType, name, interfaceInterceptor);
return unityContainer;
}
var virtualMethodInterceptor = new VirtualMethodInterceptor();
if (virtualMethodInterceptor.CanIntercept(registrationType))
{
interception
.SetInterceptorFor(registrationType, name, virtualMethodInterceptor);
return unityContainer;
}
var transparentProxyInterceptor = new TransparentProxyInterceptor();
if (transparentProxyInterceptor.CanIntercept(registrationType))
{
interception
.SetInterceptorFor(registrationType, name, transparentProxyInterceptor);
return unityContainer;
}
return unityContainer;
}
}
Related
I'm working with EF 4.5 and DbContext. At business rules layer level, I should implement checks to avoid change entity value properties in some entity scenarios. Sample: StartProjecteDate should be readonly if ProjectIsStarted but not in other status.
I follow DRY principle, for this reason, I should be able to inspect readonly properties list from context and also from UI.
My question:
Is there a DataAnnotation validator that can dynamically set properties as readonly?
(and if not, is there a different / better solution to this problem?)
Notice than I'm working with Web Forms (and Telerik) architecture, a clean and elegant pattern will be welcome.
I'm trying to set and get at run time EditableAttribute as Jesse Webb explains, but I'm not able to get dataannotation attributes from property, my code:
<EditableAttribute(False)>
<MaxLength(400, ErrorMessage:="MÃ xim 400 caracters")>
Public Property NomInvertebrat As String
Edited Nov 8 2013 after digging docs, it seems that dataanottions if for class but for instance object itself. Perhaps an iReadonlyableProperties interface may be a way.
I have a class containing extension methods that lets me read data annotations like this:
int maxRefLen = ReflectionAPI.GetProperty<Organisation, String>(x => x.Name)
.GetAttribute<StringLengthAttribute>()
.GetValueOrDefault(x => x.MaximumLength, 256);
So if you use it you should be able to do get the value of the EditableAttribute like this:
bool isEditable = ReflectionAPI.GetProperty<Foo, String>(x => x.NomInvertebrat)
.GetAttribute<EditableAttribute>()
.GetValueOrDefault(x => x.AllowEdit, true);
As for setting the data annotations at run-time, I haven't done it myself but I have read that there is a solution here: Setting data-annotations at runtime
Getting a list of all data annotations of a particular type I think would entail reading the entity framework metadata. Again I haven't tried this.
If you add that together I personally think it feels clunky rather than elegant, but you have asked for a solution using DataAnnotations and something more elegant would probably mean getting into your architecture.
I would be inclined to do this:
public bool StartDateIsReadOnly
{
//use this property client-side to disable the input
get{ return Project.IsStarted;}
}
//Implement IValidatable object to do server side validation
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext
{
bool startdateIsChanged = // I'll leave you to work out this bit
var results = new List<ValidationResult>();
if(StartDateIsReadOnly && startdateIsChanged)
results.Add(new ValidationResult("Start Date cannot be changed after project is started");
}
Here is the ReflectionAPI class:
Please note that the class includes part of a hack that #JonSkeet posted and described as "evil". I personally think this bit ain't so bad, but you should read the following references:
Override a generic method for value types and reference types.
Evil code - overload resolution workaround
public static class ReflectionAPI
{
public static int GetValueOrDefault<TInput>(this TInput a, Func<TInput, int> func, int defaultValue)
where TInput : Attribute
//Have to restrict to struct or you get the error:
//The type 'R' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'System.Nullable<T>'
{
if (a == null)
return defaultValue;
return func(a);
}
public static Nullable<TResult> GetValueOrDefault<TInput, TResult>(this TInput a, Func<TInput, TResult> func, Nullable<TResult> defaultValue)
where TInput : Attribute
where TResult : struct
//Have to restrict to struct or you get the error:
//The type 'R' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'System.Nullable<T>'
{
if (a == null)
return defaultValue;
return func(a);
}
//In order to constrain to a class without interfering with the overload that has a generic struct constraint
//we need to add a parameter to the signature that is a reference type restricted to a class
public class ClassConstraintHack<T> where T : class { }
//The hack means we have an unused parameter in the signature
//http://msmvps.com/blogs/jon_skeet/archive/2010/11/02/evil-code-overload-resolution-workaround.aspx
public static TResult GetValueOrDefault<TInput, TResult>(this TInput a, Func<TInput, TResult> func, TResult defaultValue, ClassConstraintHack<TResult> ignored = default(ClassConstraintHack<TResult>))
where TInput : Attribute
where TResult : class
{
if (a == null)
return defaultValue;
return func(a);
}
//I don't go so far as to use the inheritance trick decribed in the evil code overload resolution blog,
//just create some overloads that take nullable types - and I will just keep adding overloads for other nullable type
public static bool? GetValueOrDefault<TInput>(this TInput a, Func<TInput, bool?> func, bool? defaultValue)
where TInput : Attribute
{
if (a == null)
return defaultValue;
return func(a);
}
public static int? GetValueOrDefault<TInput>(this TInput a, Func<TInput, int?> func, int? defaultValue)
where TInput : Attribute
{
if (a == null)
return defaultValue;
return func(a);
}
public static T GetAttribute<T>(this PropertyInfo p) where T : Attribute
{
if (p == null)
return null;
return p.GetCustomAttributes(false).OfType<T>().LastOrDefault();
}
public static PropertyInfo GetProperty<T, R>(Expression<Func<T, R>> expression)
{
if (expression == null)
return null;
MemberExpression memberExpression = expression.Body as MemberExpression;
if (memberExpression == null)
return null;
return memberExpression.Member as PropertyInfo;
}
}
.NET allows you to dynamically change structure of Class by implementing System.ComponentModel.ICustomTypeDescriptor. Most serializers support this interface.
// Sample Serialization
foreach(PropertyDescriptor p in TypeDescriptor.GetProperties(obj)){
string name = p.PropertyName;
object value = p.GetValue(obj);
}
Internally TypeDescriptor uses Reflection, but the implementation allows us to override reflection attributes easily.
Here are three steps of implementation,
// Implement System.ComponentModel.ICustomTypeDescriptor Interface on
// your Entity
public class MyEntity: System.ComponentModel.ICustomTypeDescriptor
{
....
// most methods needs only call to default implementation as shown below
System.ComponentModel.AttributeCollection
System.ComponentModel.ICustomTypeDescriptor.GetAttributes()
{
return TypeDescriptor.GetAttributes(this, true);
}
string System.ComponentModel.ICustomTypeDescriptor.GetClassName()
{
return TypeDescriptor.GetClassName(this, true);
}
string System.ComponentModel.ICustomTypeDescriptor.GetComponentName()
{
return TypeDescriptor.GetComponentName(this, true);
}
System.ComponentModel.TypeConverter System.ComponentModel.ICustomTypeDescriptor.GetConverter()
{
return TypeDescriptor.GetConverter(this, true);
}
System.ComponentModel.EventDescriptor System.ComponentModel.ICustomTypeDescriptor.GetDefaultEvent()
{
return TypeDescriptor.GetDefaultEvent(this, true);
}
System.ComponentModel.PropertyDescriptor System.ComponentModel.ICustomTypeDescriptor.GetDefaultProperty()
{
return TypeDescriptor.GetDefaultProperty(this, true);
}
object System.ComponentModel.ICustomTypeDescriptor.GetEditor(Type editorBaseType)
{
return TypeDescriptor.GetEditor(this, editorBaseType, true);
}
System.ComponentModel.EventDescriptorCollection System.ComponentModel.ICustomTypeDescriptor.GetEvents(Attribute[] attributes)
{
return TypeDescriptor.GetEvents(this, attributes, true);
}
System.ComponentModel.EventDescriptorCollection System.ComponentModel.ICustomTypeDescriptor.GetEvents()
{
return TypeDescriptor.GetEvents(this, true);
}
System.ComponentModel.PropertyDescriptorCollection System.ComponentModel.ICustomTypeDescriptor.GetProperties(Attribute[] attributes)
{
return TypeDescriptor.GetProperties(this, attributes, true);
}
object System.ComponentModel.ICustomTypeDescriptor.GetPropertyOwner(System.ComponentModel.PropertyDescriptor pd)
{
return this;
}
// The Only method that needs different implementation is below
System.ComponentModel.PropertyDescriptorCollection
System.ComponentModel.ICustomTypeDescriptor.GetProperties()
{
// ... you are supposed to create new instance of
// PropertyDescriptorCollection with PropertyDescriptor
PropertyDescriptorCollection pdc = new PropertyDescriptorCollection();
foreach(PropertyDescriptor p in TypeDescriptor.GetProperties(this,true)){
// if readonly..
AtomPropertyDescriptor ap = new AtomPropertyDescriptor(p, p.Name);
// or
AtomPropertyDescriptor ap = new AtomPropertyDescriptor(p, p.Name,
true,
new XmlIgnoreAttribute(),
new ScriptIgnoreAttribute(),
new ReadOnlyAttribute());
pdc.Add(ap);
}
return pdc;
}
}
// And here is the AtomPropertyDescriptorClass
public class AtomPropertyDescriptor : PropertyDescriptor
{
PropertyDescriptor desc;
bool? readOnly = null;
public AtomPropertyDescriptor(PropertyDescriptor pd, string name,
bool? readOnly, params Attribute[] attrs) :
base(name, attrs)
{
desc = pd;
this.readOnly = readOnly;
}
public override bool CanResetValue(object component)
{
return desc.CanResetValue(component);
}
public override Type ComponentType
{
get
{
return desc.ComponentType;
}
}
public override object GetValue(object component)
{
return desc.GetValue(component);
}
public override bool IsReadOnly
{
get
{
if (readOnly.HasValue)
return readOnly.Value;
return desc.IsReadOnly;
}
}
public override Type PropertyType
{
get { return desc.PropertyType; }
}
public override void ResetValue(object component)
{
desc.ResetValue(component);
}
public override void SetValue(object component, object value)
{
desc.SetValue(component, value);
}
public override bool ShouldSerializeValue(object component)
{
return desc.ShouldSerializeValue(component);
}
}
I think what you are looking for is a custom Annotation Attribute like this:
<DisableEditAttribute(this.IsProjectStarted)>
Public Property NomInvertebrat As String
public override bool IsValid(bool value)
{
bool result = true;
// Add validation logic here.
if(value)
{
//Compare Current Value Against DB Value.
}
return result;
}
See MSDN: http://msdn.microsoft.com/en-us/library/cc668224(v=vs.98).aspx
Let's say I have the following classes Customer.cs, a context OfficeContext.cs, and a repository OfficeRepository.cs. Knowing that the context use a connection object, so it's advised to enclose it in a using statement:
public List<Customer> GetAllCustomersWithOrders()
{
using(var oContext = new OfficeContext())
{
//Code here....
}
}
My question is what if I want to re-use some of the code already in the repository? For instance, what if I want to display all the customers that ordered products but didn't receive them yet, do I need to duplicate the code?
public List<Customer> GetCustomersNotReceiveProducts()
{
using(var oContext = new OfficeContext())
{
//Re-use GetAllCustomersWithOrders() here???...
}
}
But as you can see, each time access a method, I also open instantiate a new context object. Is there any way to deal with that?
What I do is have my repositories implement IDisposable.
Then have two constructors (one default) that instaniates a new context that holds it as a class level variable. And another constructor that takes a context and uses that internally.
The on the dispose of the class the context is disposed (if the current repository instatiated it).
This removes the context out of the method level and moves it to the class level. My functions keep everything in IQueryable so one function can call another function and perform additional refinements before the database it hit.
Exmaple:
public class MemberRepository : IDisposable
{
OfficeContext db;
bool isExternalDb = false;
public MemberRepository()
{
db = new OfficeContext();
isExternalDb = false;
}
public MemberRepository(OfficeContext db)
{
this.db = db;
isExternalDb = true;
}
public IQueryable<Member> GetAllMembers()
{
var members= db.Members
return members;
}
public IQueryable<Member> GetActiveMembers()
{
var members = GetAllMembers();
var activeMembers = members.Where(m => m.isActive == true);
return activeMembers;
}
public void Dispose()
{
if (isExternalDb == false)
{
db.Dispose();
}
}
}
Then where I use the repository, I do a using at that level:
using(var memberRepository = new MemberRepository())
{
var members = memberRepository.GetActiveMembers();
}
Beginners question:
Given two classes: Myclass5 and Myclass6 how can one wire up following factory method (returned as Func)
such that
myclass5 and myclass6 instances and IMyClass that they depend on are all retrieved via autofac (assuming that these three instances are registered).
public static MyClass4 FactoryMethod(int nu)
{
if (nu == 1)
return new MyClass5(....);
if (nu == 4)
return new MyClass6(....);
throw new NotImplementedException();
}
public abstract class MyClass4
{
}
public class MyClass5 : MyClass4
{
public MyClass5(int nu, IMyClass a)
{
}
}
public class MyClass6 : MyClass4
{
public MyClass6(int nu, IMyClass a)
{
}
}
For FactoryMethod to be able to create the instances, it requires access to a container. I would suggest create a delegate type for the factory method, which makes it easy to take dependency on it. Registration goes like this:
var cb = new ContainerBuilder();
cb.RegisterType<SomeClass>().As<IMyClass>();
cb.RegisterType<MyClass5>();
cb.RegisterType<MyClass6>();
cb.Register((c, p) =>
{
var context = c.Resolve<IComponentContext>();
return new FactoryMethod(nu =>
{
var nuParameter = TypedParameter.From(nu);
switch (nu)
{
case 1:
return context.Resolve<MyClass5>(nuParameter);
case 4:
return context.Resolve<MyClass6>(nuParameter);
default:
throw new NotImplementedException();
}
});
});
var container = cb.Build();
At resolve time, you can then take a dependency on the FactoryMethod delegate type and use it to resolve instances:
var factory = container.Resolve<FactoryMethod>();
var instance5 = factory(1);
var instance6 = factory(1);
Note: the delegate instance we're creating needs a context. We cannot use the c parameter directly since that context is only temporary. Thus we must resolve a IComponentContext to "bake" into the lambda.
Update: if you would like to extract the factory implementation into a method that is not dependent on the container I would suggest the following:
public class FactoryMethodImpl
{
readonly Func<int, MyClass5> _factory5;
readonly Func<int, MyClass6> _factory6;
public FactoryMethodImpl(Func<int, MyClass5> factory5, Func<int, MyClass6> factory6)
{
_factory5 = factory5;
_factory6 = factory6;
}
public MyClass4 Create(int nu)
{
switch (nu)
{
case 1:
return _factory5(nu);
case 4:
return _factory6(nu);
default:
throw new NotImplementedException();
}
}
}
Now, change the registration code to this:
var cb = new ContainerBuilder();
cb.RegisterType<SomeClass>().As<IMyClass>();
cb.RegisterType<MyClass5>();
cb.RegisterType<MyClass6>();
cb.RegisterType<FactoryMethodImpl>().SingleInstance();
cb.Register(c=> new FactoryMethod(c.Resolve<FactoryMethodImpl>().Create));
Could anyone help me in assessing why the code below doesn't work. I'm using the common extension method for implementing Include when using IObjectset. In our repositories we were seeing this not returning correctly so I've isolated the code in test app as below. I've also included the interface based Context if this may prove relevant and a screenshot of the relevant model section. This occurs for all Includes on IObjectSet properties not just the DPASelections one I've chosen for this example.
If I update the context to return ObjectSet (still using the POCO entities) rather than IObjectSet it all works fine. When using IObjectSet and the extension method and step through the code I see that the extension method is completing correctly with a call to the ObjectQuery we're casting to but the included entities are never returned on the graph. As said, this works perfectly when I don't interface out the Context and return ObjectSet properties hence calling Include directly on ObjectSet.
I'm not getting any errors on executing the query so this isn't the same as several other questions on SO which refer to compiled queries.
Has anyone else experienced problems with this extension method implementation or can anyone spot what I'm doing wrong here?
Any help very much appreciated.
static void Main(string[] args)
{
using (var context = new AssocEntities())
{
context.ContextOptions.LazyLoadingEnabled = false;
Candidate candidate = context.Candidates
.Include("DPASelections.DPAOption")
.SingleOrDefault(c => c.Number == "N100064");
//Count is 0 when using ext. method and IObjectSet through AssocContext but correct when using Include
//on ObjectSet through AssocContext
Console.WriteLine("DPASelection count = {0}",candidate.DPASelections.Count);
//This is always null when using IObjectSet and ext. method but populated
//when using Include on ObjectSet
var option = candidate.DPASelections.First().DPAOption;
Console.WriteLine("First DPAOption = {0} : {1}",option.Id,option.Text);
}
Console.ReadLine();
}
}
public static class Extensions
{
public static IQueryable<TSource> Include<TSource>(this IQueryable<TSource> source, string path)
{
var objectQuery = source as ObjectQuery<TSource>;
if (objectQuery != null)
{
objectQuery.Include(path);
}
return source;
}
}
//Subset of custom context implementing IObjectSet as returns.
//Works fine when I return ObjectSet rather than IObjectSet and use
//the Include method directly
public partial class AssocEntities : ObjectContext
{
public const string ConnectionString = "name=AssocEntities";
public const string ContainerName = "AssocEntities";
#region Constructors
public AssocEntities()
: base(ConnectionString, ContainerName)
{
this.ContextOptions.LazyLoadingEnabled = true;
}
public AssocEntities(string connectionString)
: base(connectionString, ContainerName)
{
this.ContextOptions.LazyLoadingEnabled = true;
}
public AssocEntities(EntityConnection connection)
: base(connection, ContainerName)
{
this.ContextOptions.LazyLoadingEnabled = true;
}
#endregion
#region IObjectSet Properties
public IObjectSet<Address> Addresses
{
get { return _addresses ?? (_addresses = CreateObjectSet<Address>("Addresses")); }
}
private IObjectSet<Address> _addresses;
public IObjectSet<Answer> Answers
{
get { return _answers ?? (_answers = CreateObjectSet<Answer>("Answers")); }
}
private IObjectSet<Answer> _answers;
public IObjectSet<Candidate> Candidates
{
get { return _candidates ?? (_candidates = CreateObjectSet<Candidate>("Candidates")); }
}
}
And the model...
I needed to replace objectQuery.Include(path); with objectQuery = objectQuery.Include(path);
In .Net framework 4.0 there is a build-in Extentionmethod for Include
just add the System.Data.Entity namespace.
It uses reflection - here is how it works:
private static T CommonInclude<T>(T source, string path)
{
MethodInfo method = source.GetType().GetMethod("Include", DbExtensions.StringIncludeTypes);
if (!(method != (MethodInfo) null) || !typeof (T).IsAssignableFrom(method.ReturnType))
return source;
return (T) method.Invoke((object) source, new object[1]
{
(object) path
});
}
In Asp.net MVC the url structure goes like
http://example.com/{controller}/{action}/{id}
For each "controller", say http://example.com/blog, there is a BlogController.
But my {controller} portion of the url is not decided pre-hand, but it is dynamically determined at run time, how do I create a "dynamic controller" that maps anything to the same controller which then based on the value and determines what to do?
Same thing with {action}, if the {action} portion of my url is also dynamic, is there a way to program this scenario?
Absolutely! You'll need to override the DefaultControllerFactory to find a custom controller if one doesn't exist. Then you'll need to write an IActionInvoker to handle dynamic action names.
Your controller factory will look something like:
public class DynamicControllerFactory : DefaultControllerFactory
{
private readonly IServiceLocator _Locator;
public DynamicControllerFactory(IServiceLocator locator)
{
_Locator = locator;
}
protected override Type GetControllerType(string controllerName)
{
var controllerType = base.GetControllerType(controllerName);
// if a controller wasn't found with a matching name, return our dynamic controller
return controllerType ?? typeof (DynamicController);
}
protected override IController GetControllerInstance(Type controllerType)
{
var controller = base.GetControllerInstance(controllerType) as Controller;
var actionInvoker = _Locator.GetInstance<IActionInvoker>();
if (actionInvoker != null)
{
controller.ActionInvoker = actionInvoker;
}
return controller;
}
}
Then your action invoker would be like:
public class DynamicActionInvoker : ControllerActionInvoker
{
private readonly IServiceLocator _Locator;
public DynamicActionInvoker(IServiceLocator locator)
{
_Locator = locator;
}
protected override ActionDescriptor FindAction(ControllerContext controllerContext,
ControllerDescriptor controllerDescriptor, string actionName)
{
// try to match an existing action name first
var action = base.FindAction(controllerContext, controllerDescriptor, actionName);
if (action != null)
{
return action;
}
// #ray247 The remainder of this you'd probably write on your own...
var actionFinders = _Locator.GetAllInstances<IFindAction>();
if (actionFinders == null)
{
return null;
}
return actionFinders
.Select(f => f.FindAction(controllerContext, controllerDescriptor, actionName))
.Where(d => d != null)
.FirstOrDefault();
}
}
You can see a lot more of this code here. It's an old first draft attempt by myself and a coworker at writing a fully dynamic MVC pipeline. You're free to use it as a reference and copy what you want.
Edit
I figured I should include some background about what that code does. We were trying to dynamically build the MVC layer around a domain model. So if your domain contained a Product class, you could navigate to products\alls to see a list of all products. If you wanted to add a product, you'd navigate to product\add. You could go to product\edit\1 to edit a product. We even tried things like allowing you to edit properties on an entity. So product\editprice\1?value=42 would set the price property of product #1 to 42. (My paths might be a little off, I can't recall the exact syntax anymore.) Hope this helps!
After a little more reflection, there may be a bit simpler way for you to handle the dynamic action names than my other answer. You'll still need to override the default controller factory. I think you could define your route like:
routes.MapRoute("Dynamic", "{controller}/{command}/{id}", new { action = "ProcessCommand" });
Then on your default/dynamic controller you'd have
public ActionResult ProcessCommand(string command, int id)
{
switch(command)
{
// whatever.
}
}
You need to write your own IControllerFactory (or perhaps derive from DefaultControllerFactory) and then register it with ControllerBuilder.
Iam working with it in .Core but i'll share it's MVC version for all, after that i will share the core version
case OwnerType.DynamicPage:
var dp = mediator.Handle(new Domain.DynamicPages.DynamicPageDtoQuery { ShopId = ShopId, SeoId = seoSearchDto.Id }.AsSingle());
if (dp != null)
{
return GetDynamicPage(dp.Id);
}
break;
// some codes
private ActionResult GetDynamicPage(int id)
{
var routeObj = new
{
action = "Detail",
controller = "DynamicPage",
id = id
};
var bController = DependencyResolver.Current.GetService<DynamicPageController>();
SetControllerContext(bController, routeObj);
return bController.Detail(id);
}
// and
private void SetControllerContext(ControllerBase controller, object routeObj)
{
RouteValueDictionary routeValues = new RouteValueDictionary(routeObj);
var vpd = RouteTable.Routes["Default"].GetVirtualPath(this.ControllerContext.RequestContext, routeValues);
RouteData routeData = new RouteData();
foreach (KeyValuePair<string, object> kvp in routeValues)
{
routeData.Values.Add(kvp.Key, kvp.Value);
}
foreach (KeyValuePair<string, object> kvp in vpd.DataTokens)
{
routeData.DataTokens.Add(kvp.Key, kvp.Value);
}
routeData.Route = vpd.Route;
if (routeData.RouteHandler == null)
routeData.RouteHandler = new MvcRouteHandler();
controller.ControllerContext = new ControllerContext(this.ControllerContext.HttpContext, routeData, controller);
}