CrossHelper extension method

The CrossHelper extension method returns am HtmlHelper<M> based on a model different from the one the View is strongly typed with. It is useful, when one needs to post the View to a controller that uses a different ViewModel. Its signature is:

 

 public static HtmlHelper<T> CrossHelper<T>(
            this HtmlHelper htmlHelper,
            T crossViewModel, string prefix = "")

 

Where crossViewModel is the other ViewModel, and prefix, if specified, is added as prefix to all input fields names.  prefix is usefull when crossViewModel is only a part of the ViewModel of the Action Method that receives the Post.

In-Line Transformations 

All Mvc controls toolkit controls are based on the idea of model transformation. That is, a part of ViewModel is transformed into another object that is more adequate to the way data have to be displayed, and then, when the View is posted, the inverse transformation is applied to get the original data type filled with the user input. More details on this subject can be found in the section that explains how to define new controls here. We remember just that both the direct and the inverse transformations are specified by providing an implementation of the IDisplayModel interface.

In the section  Client Block complete example we presented an example where we allows the user to edit a list of keywords of the ViewModel in a ListBox by specifying a a class that is serialized in Javascript and used as client-side ViewModel. To achieve this we need to add to the original keyword list a new property of type string that is used to contain the new keywords to add to the list and another string list to contain all keywords selected by the user in the ListBox(selection is used to specify the items to be removed). 

Thus, in order to achieve our goal we need to transform the initial strings list into a complex object with three properties, and then, when the view is posted, to extract again the keywords list edited by the user to fill the original property of the ViewModel.

As a first step we need to implent the complex object and let it implements the IDisplayModel interface:

 

    public class ClientViewModel:IDisplayModel
    {
        public List<string> Keywords { get; set; }
        public List<string> SelectedKeywords { get; set; }
        public string ItemToAdd { get; set; }
        public ClientViewModel()
        {
            
            SelectedKeywords = new List<string>();
            ItemToAdd = "";
        }

        public object ExportToModel(Type TargetType, params object[] context)
        {
            return Keywords;
        }

        public void ImportFromModel(object model, params object[] context)
        {
            Keywords = model as List<string>;
            if (Keywords == null)
                Keywords = new List<string>();
        }
    }

 

ImportFromModel is the direct transformation and ExportToModel the inverse one. In our case both transformations are very simple. The first one just take the original keyword list of the ViewModel and store it in the Keywords property of our ClientViewModel class, while the inverse transformation just takes the Keywords property of the above class that contains the list after the user editing and returns it to the original ViewModel. Now suppose that the origina keyword list is contained in a property of the ViewModel called ClientKeywords:

 

            @{
           var clientKeywordsHelper =
                  Html.TransformedHelper(
                      m => m.ClientKeywords,
                      new ClientViewModel()); }

 

The above instruction create an instance of HtmlHelper<ClientViewModel> that can be used to render all properties of the ClientViewModel class and returns it into the clientKeywordsHelper variable. What we need to do is just to use this HtmlHelper as it were the original HttmlHelper of our View, the Mvc Controls Toolkit willl automatically do the job of applying both the direct and the inverse transformation when needed.

The full code of the example is in the  Client Block complete example section. If you need to refer from JavaScript code to the id of  input fields that have been rendered with helpers returned by in-line transformations please see the PrefixedId helper.

The TransformedHelper extension method renders in the page some information about the transformation we have carried out  and return the new helper. During the post the information about the transformation applied, is used by the model binder in order to rebuild the original model. If you need more control on where such information is rendered within the page you can use the Html.TransformHelper extension method that return the information about the transformation as an MvcHtmlString, so you can decide where to put it, and pass the new helper as an output parameter:

 

public static MvcHtmlString TransformHelper<VM, M, NM>(
           this HtmlHelper<VM> htmlHelper,
           Expression<Func<VM, M>> expression,
           NM newModel,
           out HtmlHelper<NM> newHtmlHelper,
           params object[] args)
            where NM : IDisplayModel

 

If our transformation is encoded by an implementation of the IUpdateModel Interface instead than an implementation of IDisplayModel,  we can get a new helper by using TransformedUpdateHelper instead of TransformedHelper, or TransformUpdateHelper instead of TransformHelper, and passing them an expression that selects the DataType to transform as first argument, and an instance of the IUpdateModel implementation as second argument. See Core Functions: Defining Your Controls! for more information on the use of the IUpdateModel interface.

Last edited Jun 22 at 11:40 AM by frankabbruzzese, version 14

Comments

No comments yet.