Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Replaced params dictionary population with a binder implementation

  • Loading branch information...
commit d84581521581657a996761ff357c272c4da418cc 1 parent 4f9355d
Ivan Porto Carrero casualjim authored
3  .gitignore
@@ -20,5 +20,4 @@ IronRubyMvc/Controllers/._controller.rb
20 20 IronRubyMvc/Core/._RubyEngine.cs
21 21 dependencies/IronRuby.Tests.exe
22 22 dependencies/IronRuby.Tests.pdb
23   -IronRubyMvcLibrarySpecs/bin/*.*
24   -ParamsBinder.cs
  23 +IronRubyMvcLibrarySpecs/bin/*.*
81 IronRubyMvc/Controllers/ParamsBinder.cs
... ... @@ -0,0 +1,81 @@
  1 +#region Usings
  2 +
  3 +using System.Collections.Generic;
  4 +using System.Globalization;
  5 +using System.Web.Mvc.IronRuby.Extensions;
  6 +using Microsoft.Scripting;
  7 +
  8 +#endregion
  9 +
  10 +namespace System.Web.Mvc.IronRuby.Controllers
  11 +{
  12 + public class ParamsBinder : IModelBinder
  13 + {
  14 + private IDictionary<SymbolId, object> _params;
  15 +
  16 + #region IModelBinder Members
  17 +
  18 + public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
  19 + {
  20 + controllerContext.EnsureArgumentNotNull("controllerContext");
  21 + bindingContext.EnsureArgumentNotNull("bindingContext");
  22 +
  23 + _params = (bindingContext.Model as Dictionary<SymbolId, object>) ?? new Dictionary<SymbolId, object>();
  24 + bindingContext.ValueProvider.ForEach(pair =>
  25 + {
  26 + bindingContext.ModelState.SetModelValue(pair.Key, pair.Value);
  27 + _params.Add(pair.Key.ToSymbolId(), pair.Value.RawValue);
  28 + });
  29 +// var request = controllerContext.HttpContext.Request;
  30 +// var modelState = controllerContext.Controller.ViewData.ModelState;
  31 +//
  32 +// PopulateParamsWithFormData(request, modelState);
  33 +// PopulateParamsWithQueryStringData(request, modelState);
  34 +// PopulateParamsWithRouteData(controllerContext.RouteData.Values);
  35 +
  36 + return _params;
  37 + }
  38 +
  39 + #endregion
  40 +
  41 +// private void PopulateParamsWithFormData(HttpRequestBase request, IDictionary<string, ModelState> modelState)
  42 +// {
  43 +// foreach (string key in request.Form.Keys)
  44 +// {
  45 +// var symbolKey = SymbolTable.StringToId(key);
  46 +// _params[symbolKey] = request.Form[key];
  47 +// modelState.Add(key, CreateModelState(request.Form[key]));
  48 +// }
  49 +// }
  50 +//
  51 +// private void PopulateParamsWithQueryStringData(HttpRequestBase request, IDictionary<string, ModelState> modelState)
  52 +// {
  53 +// foreach (string key in request.QueryString.Keys)
  54 +// {
  55 +// var symbolKey = SymbolTable.StringToId(key);
  56 +// var value = request.QueryString[key];
  57 +// _params[symbolKey] = value;
  58 +// modelState.Add(key, CreateModelState(value));
  59 +// }
  60 +// }
  61 +//
  62 +// private void PopulateParamsWithRouteData(IEnumerable<KeyValuePair<string, object>> routeValueDictionary)
  63 +// {
  64 +// foreach (var item in routeValueDictionary)
  65 +// {
  66 +// var key = SymbolTable.StringToId(item.Key);
  67 +// _params[key] = item.Value;
  68 +// }
  69 +// }
  70 +//
  71 +// private static ModelState CreateModelState(string value)
  72 +// {
  73 +// return new ModelState {Value = CreateValueProviderResult(value)};
  74 +// }
  75 +//
  76 +// private static ValueProviderResult CreateValueProviderResult(string value)
  77 +// {
  78 +// return new ValueProviderResult(value, value, CultureInfo.CurrentCulture);
  79 +// }
  80 + }
  81 +}
69 IronRubyMvc/Controllers/RubyController.cs
@@ -19,7 +19,7 @@ public class RubyController : Controller
19 19 {
20 20 private readonly Dictionary<object, object> _viewData = new Dictionary<object, object>();
21 21 private IRubyEngine _engine;
22   - private IDictionary<object, object> _params;
  22 + private IDictionary<SymbolId, object> _params;
23 23
24 24 public string ControllerName { get; internal set; }
25 25 public RubyClass RubyType { get; private set; }
@@ -30,13 +30,13 @@ public string ControllerClassName
30 30 }
31 31
32 32 [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Params")]
33   - public IDictionary<object, object> Params
  33 + public IDictionary<SymbolId, object> Params
34 34 {
35 35 get
36 36 {
37 37 if (_params == null)
38 38 {
39   - PopulateParams();
  39 +
40 40 }
41 41
42 42 return _params;
@@ -45,57 +45,19 @@ public string ControllerClassName
45 45
46 46 private void PopulateParams()
47 47 {
48   - //TODO: Possibly replace this with a binder implementation
  48 + var modelType = typeof (IDictionary<SymbolId, object>);
49 49 var request = ControllerContext.HttpContext.Request;
50   - _params =
51   - new Dictionary<object, object>(ControllerContext.RouteData.Values.Count +
52   - request.QueryString.Count + request.Form.Count);
53   - PopulateParamsWithRouteData();
54   -
55   - PopulateParamsWithQueryStringData(request);
56   -
57   - PopulateParamsWithFormData(request);
58   - }
59   -
60   - private void PopulateParamsWithFormData(HttpRequestBase request)
61   - {
62   - foreach (string key in request.Form.Keys)
63   - {
64   - var symbolKey = SymbolTable.StringToId(key);
65   - _params[symbolKey] = request.Form[key];
66   - ModelState.Add(key, CreateModelState(request.Form[key]));
67   - }
68   - }
69   -
70   - private void PopulateParamsWithQueryStringData(HttpRequestBase request)
71   - {
72   - foreach (string key in request.QueryString.Keys)
73   - {
74   - var symbolKey = SymbolTable.StringToId(key);
75   - var value = request.QueryString[key];
76   - _params[symbolKey] = value;
77   - ModelState.Add(key, CreateModelState(value));
78   - }
79   - }
80   -
81   - private void PopulateParamsWithRouteData()
82   - {
83   - foreach (var item in ControllerContext.RouteData.Values)
84   - {
85   - var key = SymbolTable.StringToId(item.Key);
86   - _params[key] = item.Value;
87   -// ModelState.Add(item.Key, CreateModelState(item.Value.ToString()));
88   - }
89   - }
90   -
91   - private static ModelState CreateModelState(string value)
92   - {
93   - return new ModelState {Value = CreateValueProviderResult(value)};
94   - }
95   -
96   - private static ValueProviderResult CreateValueProviderResult(string value)
97   - {
98   - return new ValueProviderResult(value, value, CultureInfo.CurrentCulture);
  50 + var binder = Binders.GetBinder(modelType);
  51 + var modelBindingContext = new ModelBindingContext
  52 + {
  53 + Model = new Dictionary<SymbolId, object>(ControllerContext.RouteData.Values.Count + request.QueryString.Count + request.Form.Count),
  54 + ModelName = "params",
  55 + ModelState = ModelState,
  56 + ModelType = modelType,
  57 + ValueProvider = ValueProvider
  58 + };
  59 + _params = binder.BindModel(ControllerContext, modelBindingContext) as IDictionary<SymbolId, object>;
  60 +
99 61 }
100 62
101 63 internal void InternalInitialize(ControllerConfiguration config)
@@ -104,6 +66,7 @@ internal void InternalInitialize(ControllerConfiguration config)
104 66 _engine = config.Engine;
105 67 ControllerName = config.RubyClass.Name.Replace("Controller", string.Empty);
106 68 RubyType = config.RubyClass;
  69 + Binders = RubyModelBinders.Binders;
107 70 }
108 71
109 72 protected override void Execute(RequestContext requestContext)
59 IronRubyMvc/Controllers/RubyModelBinders.cs
... ... @@ -0,0 +1,59 @@
  1 +#region Usings
  2 +
  3 +using System.Collections.Generic;
  4 +using System.Reflection;
  5 +using Microsoft.Scripting;
  6 +
  7 +#endregion
  8 +
  9 +namespace System.Web.Mvc.IronRuby.Controllers
  10 +{
  11 + public class RubyModelBinders
  12 + {
  13 + private static readonly ModelBinderDictionary _binders = CreateDefaultBinderDictionary();
  14 +
  15 + public static ModelBinderDictionary Binders
  16 + {
  17 + get { return _binders; }
  18 + }
  19 +
  20 + internal static IModelBinder GetBinderFromAttributes(ICustomAttributeProvider element, Func<string> errorMessageAccessor)
  21 + {
  22 + // this method is used to get a custom binder based on the attributes of the element passed to it.
  23 + // it will return null if a binder cannot be detected based on the attributes alone.
  24 +
  25 + var attrs = (CustomModelBinderAttribute[]) element.GetCustomAttributes(typeof (CustomModelBinderAttribute), true /* inherit */);
  26 + if (attrs == null)
  27 + {
  28 + return null;
  29 + }
  30 +
  31 + switch (attrs.Length)
  32 + {
  33 + case 0:
  34 + return null;
  35 +
  36 + case 1:
  37 + var binder = attrs[0].GetBinder();
  38 + return binder;
  39 +
  40 + default:
  41 + var errorMessage = errorMessageAccessor();
  42 + throw new InvalidOperationException(errorMessage);
  43 + }
  44 + }
  45 +
  46 + private static ModelBinderDictionary CreateDefaultBinderDictionary()
  47 + {
  48 + // We can't add a binder to the HttpPostedFileBase type as an attribute, so we'll just
  49 + // prepopulate the dictionary as a convenience to users.
  50 +
  51 + var binders = new ModelBinderDictionary
  52 + {
  53 + {typeof (IDictionary<SymbolId, object>), new ParamsBinder()},
  54 + {typeof (HttpPostedFileBase), new HttpPostedFileBaseModelBinder()}
  55 + };
  56 + return binders;
  57 + }
  58 + }
  59 +}
27 IronRubyMvc/Extensions/StringExtensions.cs
... ... @@ -1,6 +1,7 @@
1 1 #region Usings
2 2
3 3 using System.Globalization;
  4 +using Microsoft.Scripting;
4 5
5 6 #endregion
6 7
@@ -46,6 +47,32 @@ public static string FormattedWith(this string value, params object[] parameters
46 47 return string.Format(CultureInfo.CurrentUICulture, value, parameters);
47 48 }
48 49
  50 + /// <summary>
  51 + /// Converts the string to a case-sensitive <see cref="SymbolId"/>
  52 + /// </summary>
  53 + /// <param name="value">The value.</param>
  54 + /// <returns></returns>
  55 + public static SymbolId ToSymbolId(this string value)
  56 + {
  57 + return ToSymbolId(value, true);
  58 + }
  59 +
  60 + /// <summary>
  61 + /// Converts the string to a <see cref="SymbolId"/>
  62 + /// </summary>
  63 + /// <param name="value">The value.</param>
  64 + /// <param name="caseSensitive">if set to <c>true</c> the <see cref="SymbolId"/> will be case-sensitive.</param>
  65 + /// <returns></returns>
  66 + public static SymbolId ToSymbolId(this string value, bool caseSensitive)
  67 + {
  68 + return caseSensitive ? SymbolTable.StringToId(value) : SymbolTable.StringToCaseInsensitiveId(value);
  69 + }
  70 +
  71 + /// <summary>
  72 + /// Ensures the argument not empty.
  73 + /// </summary>
  74 + /// <param name="value">The value.</param>
  75 + /// <param name="argumentName">Name of the argument.</param>
49 76 public static void EnsureArgumentNotEmpty(this string value, string argumentName)
50 77 {
51 78 if (value.IsNullOrBlank()) throw new ArgumentNullException(argumentName, "Cannot be null");
2  IronRubyMvc/System.Web.Mvc.IronRuby.csproj
@@ -90,8 +90,10 @@
90 90 </ItemGroup>
91 91 <ItemGroup>
92 92 <Compile Include="Controllers\ControllerConfiguration.cs" />
  93 + <Compile Include="Controllers\ParamsBinder.cs" />
93 94 <Compile Include="Controllers\RubyActionMethodSelector.cs" />
94 95 <Compile Include="Controllers\RubyActionSelector.cs" />
  96 + <Compile Include="Controllers\RubyModelBinders.cs" />
95 97 <Compile Include="Core\AssemblyStreamContentProvider.cs" />
96 98 <Compile Include="Core\IPathProvider.cs" />
97 99 <Compile Include="Core\IRubyEngine.cs" />

0 comments on commit d845815

Please sign in to comment.
Something went wrong with that request. Please try again.