Commits

Anonymous committed 8186e19

Added alias functionality directly on model binding properties

  • Participants
  • Parent commits 431c575

Comments (0)

Files changed (16)

nuget/ActionParameterAlias.dll.nuspec

 <package >
   <metadata>
     <id>ActionParameterAlias</id>
-    <version>5.0.0</version>
+    <version>6.0.0</version>
     <authors>Jeffrey Palermo</authors>
     <owners>Jeffrey Palermo</owners>
     <licenseUrl>http://www.apache.org/licenses/LICENSE-2.0.html</licenseUrl>
     <projectUrl>https://bitbucket.org/jeffreypalermo/action-parameter-alias</projectUrl>
     <requireLicenseAcceptance>false</requireLicenseAcceptance>
-    <description>Adds ability to support aliases for model binding.  Set action parameter to "product" and place "productid" on querystring. i.e. [ParameterAlias("product", "productid")]
-        public ActionResult Index(Product product)</description>
-    <releaseNotes></releaseNotes>
+    <description>Adds ability to support aliases for model binding.  Set action parameter to "product" and place "productid" on querystring. i.e. public ActionResult Index([Alias("pid"]Product product)</description> ... add global filter ... filters.Add(new AliasInitializer());
+    <releaseNotes>Added global filter AliasInitializer, which enables adding Alias attributes directly on model binding properties</releaseNotes>
     <copyright>Copyright 2012</copyright>
     <tags>mvc model binding method action parameter alias value provider binder providers</tags>
   </metadata>

nuget/lib/net40/ActionParameterAlias.dll

Binary file modified.

src/ActionParameterAlias/ActionParameterAlias.csproj

   </ItemGroup>
   <ItemGroup>
     <Compile Include="ActionParameterAlias.cs" />
+    <Compile Include="Alias.cs" />
+    <Compile Include="AliasModelBinder.cs" />
     <Compile Include="ParameterAliasAttribute.cs" />
     <Compile Include="ParameterAliasValueProvider.cs" />
     <Compile Include="ParameterAliasValueProviderFactory.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="AliasInitializer.cs" />
   </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 

src/ActionParameterAlias/Alias.cs

+using System;
+using System.Web.Mvc;
+
+namespace ActionParameterAlias
+{
+    [AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
+    public class Alias : Attribute
+    {
+        public string Name { get; set; }
+
+        public Alias(string aliasName)
+        {
+            Name = aliasName;
+        }
+    }
+}

src/ActionParameterAlias/AliasInitializer.cs

+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Web.Mvc;
+using System.Linq;
+
+namespace ActionParameterAlias
+{
+    public class AliasInitializer : IAuthorizationFilter
+    {
+        public void OnAuthorization(AuthorizationContext filterContext)
+        {
+            var parameterAliases = new List<ActionParameterAlias>();
+            ParameterDescriptor[] parameterDescriptors = filterContext.ActionDescriptor.GetParameters();
+            AddAliases(parameterAliases, parameterDescriptors);
+
+            IValueProvider valueProvider = filterContext.Controller.ValueProvider;
+            var provider = new ValueProviderCollection {valueProvider};
+            foreach (ActionParameterAlias @alias in parameterAliases)
+            {
+                provider.Add(new ParameterAliasValueProvider(valueProvider, @alias));                    
+            }
+
+            filterContext.Controller.ValueProvider = provider;
+        }
+
+        private static void AddAliases(List<ActionParameterAlias> parameterAliases, IEnumerable<ParameterDescriptor> parameterDescriptors)
+        {
+            foreach (ParameterDescriptor descriptor in parameterDescriptors)
+            {
+                AddAlias(parameterAliases, descriptor, descriptor.ParameterType, descriptor.ParameterName);
+            }
+        }
+
+        private static void AddAliases(List<ActionParameterAlias> parameterAliases, IEnumerable<PropertyInfo> incomingPropertyInfos)
+        {
+            foreach (PropertyInfo propertyInfo in incomingPropertyInfos)
+            {
+                AddAlias(parameterAliases, propertyInfo, propertyInfo.PropertyType, propertyInfo.Name);
+            }
+        }
+
+        private static void AddAlias(List<ActionParameterAlias> parameterAliases, ICustomAttributeProvider propertyInfo, Type propertyType, string propertyName)
+        {
+            string parameterName = propertyName;
+            var aliases = (Alias[]) propertyInfo.GetCustomAttributes(typeof (Alias), false);
+            if (aliases.Any())
+            {
+                foreach (Alias @alias in aliases)
+                {
+                    parameterAliases.Add(new ActionParameterAlias(parameterName, @alias.Name));                           
+                }
+            }
+
+            PropertyInfo[] propertyInfos = propertyType.GetProperties();
+            AddAliases(parameterAliases, propertyInfos);
+        }
+    }
+}

src/ActionParameterAlias/AliasModelBinder.cs

+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Web.Mvc;
+using System.Linq;
+
+namespace ActionParameterAlias
+{
+    public class AliasModelBinder : DefaultModelBinder
+    {
+        readonly ValueProviderCollection _valueProviderCollection = new ValueProviderCollection();
+
+        protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, System.Type modelType)
+        {
+            object model = base.CreateModel(controllerContext, bindingContext, modelType);
+            return model;
+        }
+
+        protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor)
+        {
+            base.BindProperty(controllerContext, bindingContext, propertyDescriptor);
+        }
+        public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
+        {
+            ValueProviderCollection collection = new ValueProviderCollection();
+            foreach (string alias in bindingContext.ModelMetadata.AdditionalValues.Keys)
+            {
+                collection.Add(new ParameterAliasValueProvider(controllerContext,
+                                                                           new ActionParameterAlias(
+                                                                               bindingContext.ModelName,
+                                                                               alias)));
+            }
+            collection.Add(bindingContext.ValueProvider);
+            bindingContext.ValueProvider = collection;
+            return base.BindModel(controllerContext, bindingContext);
+        }
+//        protected override PropertyDescriptorCollection GetModelProperties(ControllerContext controllerContext, ModelBindingContext bindingContext)
+//        {
+//            PropertyDescriptorCollection propertyDescriptorCollection = base.GetModelProperties(controllerContext, bindingContext);
+//            foreach (PropertyDescriptor descriptor in propertyDescriptorCollection)
+//            {
+//                AddAliasesForProperty(controllerContext, bindingContext, descriptor);
+//            }
+//
+//            return propertyDescriptorCollection;
+//        }
+
+        private void AddAliasesForProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor)
+        {
+            IEnumerable<Alias> aliases = propertyDescriptor.Attributes.OfType<Alias>();
+            if (aliases.Any())
+            {
+                foreach (var aliasAttribute in aliases)
+                {
+                    _valueProviderCollection.Add(new ParameterAliasValueProvider(controllerContext,
+                                                                           new ActionParameterAlias(
+                                                                               propertyDescriptor.Name,
+                                                                               aliasAttribute.Name)));
+                }
+            }
+        }
+    }
+}

src/ActionParameterAlias/ParameterAliasValueProvider.cs

             if (!_actionParameterAlias.ActionParameter.Equals(key, StringComparison.InvariantCultureIgnoreCase))
                 return null;
 
-            return _defaultValueProvider().GetValue(_actionParameterAlias.Alias);
+            ValueProviderResult result = _defaultValueProvider().GetValue(_actionParameterAlias.Alias);
+            return result;
         }
     }
 }

src/Sample/Controllers/HomeController.cs

 {
     public class HomeController : Controller
     {
-        public ActionResult Index()
+        public ActionResult Index(User user, [Alias("un2")][Alias("un3")] string uname)
         {
             ViewBag.Message = "Welcome to ASP.NET MVC!";
-
+            ViewBag.Param = user.Username;
+            ViewBag.Param2 = uname;
+            ViewBag.Param3 = user.UserAgent;
             return View();
         }
 
             return View("Search", product);
         }
 
+        public ActionResult Login(LoginRequest request)
+        {
+            return View(request);
+        }
+
         public ActionResult About()
         {
             return View();

src/Sample/Controllers/LoginRequest.cs

+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.Web.Mvc;
+
+namespace ActionParameterAlias.Sample.Controllers
+{
+    public class LoginRequest
+    {
+        public LoginRequest()
+        {
+            Agreement = new TermsAgreement();
+        }
+        [Alias("un")]
+        [Category("un")]
+        public string UserName { get; set; }
+
+        public string Password { get; set; }
+        public string HTTP_USER_AGENT { get; set; }
+
+        public TermsAgreement Agreement { get; set; }
+    }
+
+    [Bind(Prefix = "")]
+    public class TermsAgreement
+    {
+        public bool Agreed { get; set; }
+        public string ComputerUser { get; set; }
+        [Category("HTTP_USER_AGENT")]
+        public string HTTP_USER_AGENT { get; set; }
+    }
+}

src/Sample/Controllers/User.cs

+namespace ActionParameterAlias.Sample.Controllers
+{
+    public class User
+    {
+        [Alias("un")]
+        public string Username { get; set; }
+
+        [Alias("HTTP_USER_AGENT")]
+        public string UserAgent { get; set; }
+    }
+}

src/Sample/Global.asax.cs

-using System.Web;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.Web;
 using System.Web.Mvc;
 using System.Web.Routing;
+using System.Linq;
 
 namespace ActionParameterAlias.Sample
 {
         public static void RegisterGlobalFilters(GlobalFilterCollection filters)
         {
             filters.Add(new HandleErrorAttribute());
+            filters.Add(new AliasInitializer());
         }
 
         public static void RegisterRoutes(RouteCollection routes)
             AreaRegistration.RegisterAllAreas();
             RegisterGlobalFilters(GlobalFilters.Filters);
             RegisterRoutes(RouteTable.Routes);
-            ValueProviderFactories.Factories.Add(new ParameterAliasValueProviderFactory(
-                                                     new ActionParameterAlias("product", "product-id"),
-                                                     new ActionParameterAlias("product", "prodid")));
+            ValueProviderFactories.Factories.Add(new ServerVariablesValueProviderFactory());
         }
     }
 }

src/Sample/Sample.csproj

   </ItemGroup>
   <ItemGroup>
     <Compile Include="Controllers\HomeController.cs" />
+    <Compile Include="Controllers\LoginRequest.cs" />
     <Compile Include="Controllers\Product.cs" />
     <Compile Include="Controllers\ProductTypeConverter.cs" />
+    <Compile Include="Controllers\User.cs" />
     <Compile Include="Global.asax.cs">
       <DependentUpon>Global.asax</DependentUpon>
     </Compile>
     <Compile Include="Models\AccountModels.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="ServerVariablesValueProvider.cs" />
+    <Compile Include="ServerVariablesValueProviderFactory.cs" />
   </ItemGroup>
   <ItemGroup>
     <Content Include="Content\themes\base\images\ui-bg_flat_0_aaaaaa_40x100.png" />
       <Name>ActionParameterAlias</Name>
     </ProjectReference>
   </ItemGroup>
+  <ItemGroup>
+    <Content Include="Views\Home\Login.cshtml" />
+  </ItemGroup>
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
   <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 

src/Sample/ServerVariablesValueProvider.cs

+using System.Globalization;
+using System.Web.Mvc;
+
+namespace ActionParameterAlias.Sample
+{
+    public class ServerVariablesValueProvider : IValueProvider
+    {
+        private readonly ControllerContext _controllerContext;
+
+        public ServerVariablesValueProvider(ControllerContext controllerContext)
+        {
+            _controllerContext = controllerContext;
+        }
+
+        public bool ContainsPrefix(string prefix)
+        {
+            bool containsPrefix = _controllerContext.HttpContext.Request.ServerVariables[prefix] != null;
+            return containsPrefix;
+        }
+
+        public ValueProviderResult GetValue(string key)
+        {
+            string rawValue = _controllerContext.HttpContext.Request.ServerVariables.Get(key);
+            if (rawValue == null) return null;
+
+            return new ValueProviderResult(rawValue, rawValue, CultureInfo.InvariantCulture);
+        }
+    }
+}

src/Sample/ServerVariablesValueProviderFactory.cs

+using System.Web.Mvc;
+
+namespace ActionParameterAlias.Sample
+{
+    public class ServerVariablesValueProviderFactory : ValueProviderFactory
+    {
+        public override IValueProvider GetValueProvider(ControllerContext controllerContext)
+        {
+            return new ServerVariablesValueProvider(controllerContext);
+        }
+    }
+}

src/Sample/Views/Home/Index.cshtml

-@{
+@model String
+           
+@{
     ViewBag.Title = "Home Page";
 }
 
 <h2>@ViewBag.Message</h2>
+<h2>1 @ViewBag.Param</h2>
+<h2>2 @ViewBag.Param2</h2>
+<h2>3 @ViewBag.Param3</h2>
 <p><a href="/Home/Search?pid=PIDRO123234&p_id=P_IDRO123234&productid=PRODUCTIDRO123234">Click here: /Home/Search?pid=PIDRO123234&amp;p_id=P_IDRO123234&amp;productid=PRODUCTIDRO123234</a></p>
 <p>
     To learn more about ASP.NET MVC visit <a href="http://asp.net/mvc" title="ASP.NET MVC Website">http://asp.net/mvc</a>.

src/Sample/Views/Home/Login.cshtml

+@model ActionParameterAlias.Sample.Controllers.LoginRequest
+
+@{
+    ViewBag.Title = "title";
+}
+
+<h2>title</h2>
+@Model.UserName<br/>
+@Model.Password<br/>
+@Model.Agreement.Agreed<br/>
+@Model.Agreement.ComputerUser<br/>
+@Model.HTTP_USER_AGENT<br/>
+@Model.Agreement.HTTP_USER_AGENT<br/>