How to Use ValueInjecter with Asp net MVC ViewModel

Saturday, March 22, 2014

What is ValueInjecter ?
  • An Open Source Free product
  • Its a Mapper
  • It lets you define your own convention-based matching algorithms (ValueInjections)
  • In order to match up (inject) Source values to Destination values
  • With the ValueInjecter you inject values from the properties of source into properties of target object using ValueInjections
  • Each ValueInjection has its own conventions of which properties to match and how to transform the value.
  • By Default maps the properties with the Same Name and Same Type
  • But you can override TypesMatch to change this from source to the ones in the target
  •                                                                                                                    
When To Use ?
  • When we need to Map Domain Model to ViewModel and Vice-versa

How to Download?
  • You can download the "Omu.ValueInjecter.dll" from CodePlex located Here

download

How to Set Reference for above .dll on Your Project ?
  • On your Web Project Add Reference to the "Omu.ValueInjecter.dll"

Add Reference

Lets Try with Simple Example

  • C# , MVC 3 and Visual Studio 2010 has been used.
  • Please Follow an Inline Comments on Code.
  • Simple application with Product Name text box,Retail Price text box and Save button.   
       
Our Simple View Looks Like below


Our Simple View


Our Domain Model Looks like below

 public class Product
    {
        public Product() { Id = Guid.NewGuid() //create Guid as Primary key }

        public Guid Id { get; set; }
        public string ProductName { get; set; }
        public decimal RetailerPrice { get; set; }
       
        public virtual Provider Provider { get; set; }
    }

Our ViewModel Looks like below

public class ProductViewModel
    {
        public Guid Id { get; set; }

        [Required(ErrorMessage = "required")]
        public string ProductName { get; set; }

        [Required(ErrorMessage = "required")]
        public decimal RetailerPrice { get; set; }
             
    }

Our Controller Looks like below

        [HttpPost]
        public ActionResult AddProduct(ProductViewModel productViewModel, string providerKey)
        {
            //get provider from repository
            var provider = Repository.GetProvider(providerKey);

            //create Product domain object
            var productObj = new Product();

            //usage of ValueInjecter
            //source object as productViewModel
            //target object as productObj
            //type FilterId for keep target property Id value
            //not overridden from source property Id value (will explain later)
            productObj.InjectFrom<FilterId>(productViewModel);

            //If something missing then map as below
            productObj.Provider = provider;

            if (ModelState.IsValid) //check validation
            {
                //save for repository
                Repository.AddProduct(productObj);
                return RedirectToAction("AddProduct", new { providerKey = providerKey });
            }
            else
            {
                return View(productViewModel);
            }
        }

Our FilterId  Custom Class Looks like below

FilterId  Custom Class

using Omu.ValueInjecter;

namespace PawLoyalty.Web.Areas.Providers.ValueInjections
{
    public class FilterId : LoopValueInjection
    {
        //sourcePropName "Id" will not map to target property name "Id"
        //ie: Keep target property value as it is (not change from mapping)
        protected override bool UseSourceProp(string sourcePropName)
        {
            return sourcePropName  !=  "Id";
        }
    }
}

Why We Need FilterId Custom Class ?

# Its a Custom class inherited from LoopValueInjection class

# On our Domain Model (Product) we have to Initialize property Id of type Guid when creates
   an object (inside a constructor) as a Primary Key.

# So After that generated Id will save on the Database at the end

# When we use productObj.InjectFrom(productViewModel) Line of code (default)
   Without <FilterId> then source object (productViewModel) will override the
   target  objects Id with value {00000000-0000-0000-0000-000000000000}.

# So for avoid such a situation we have to use FilterId Custom class as above

#  i.e When we need to keep without changing target property Id value (productObj).
          Because it is our Primary key.

What Says Creator of ValueInjecter ? - By Valentin Plamadeala

Another way of doing the FilterId injection would be like this:

Method 1:
     
public class FilterId : ConventionInjection
 {
   protectedoverride boolMatch(ConventionInfo c)
    {
      returnc.SourceProp.Name != "Id"&& c.SourceProp.Name == c.TargetProp.Name
             && c.SourceProp.Type == c.TargetProp.Type;
    }
 }

Method 2 :

public class IngnoreProps : ConventionInjection
    {
        privatereadonly string[] _ignores;

        publicIngnoreProps()
        {
        }

        publicIngnoreProps(params string[] ignores)
        {
            _ignores = ignores;
        }

        protectedoverride boolMatch(ConventionInfo c)
        {
            return(_ignores == null || !_ignores.Contains(c.SourceProp.Name)) &&
                   c.SourceProp.Name == c.TargetProp.Name
                   && c.SourceProp.Type == c.TargetProp.Type;
        }
    }

and use it like this:

    target.InjectFrom(newIgnoreProps("Id"), source);

Special Thanks

I must put special thanks for Valentin Plamadeala (Creator of ValueInjecter) who gave me a feedback for my Article and also put that on codeplex. Thanks Valentin.I hope you will create lots of this kind of value added components behalf of us in future also.Good Luck.


What are the Features of ValueInjecter ?
  • Its Simple and Very Flexible
  • Its something like mozilla with its plugins, you create ValueInjections and use them
  • There are built-in injections for flattening, unflattering
  • Can use with MVC ,Win-Forms,Web-Forms,Silverlight,WPF and Data Access Situations
  • Can also use ValueInjecter to map from Anonymous and Dynamic objects
  • Valueinjecter has a default injection .InjectFrom() that does the properties with the Same Name and Same Type.
  • For everything else you can Create your Custom Valueinjections with individual mapping logic/rules, more like aspectse.g. from all properties of Type Foo to all properties of type Bar
                 What is Aspects - Aspect Oriented Programming (AOP) involves breaking down
                                               program logic into distinct parts.

Do you need to Dive Deep ends of  ValueInjecter ?
  • Stackoverflow  Here

Conclusion
  • Above I have showed very simple usage of ValueInjecter Mapper
  • If you need to learn more about ValueInjecter then you have to follow above mentioned Links
  • This mapper is nicely fit with Asp.Net MVC ViewModel developments for very simple to very complex scenarios

I hope this helps to You.Comments and feedback greatly appreciated.

Happy Coding.

Related Article


Related Posts by Categories

0 comments:

Post a Comment