- Fixed MR-84
[castle.git] / MonoRail / Castle.Monorail.JSONSupport / JSONBinderAttribute.cs
blob98e2c1cf330c14d1d0049dbe721763922c1010df
1 // Copyright 2004-2007 Castle Project - http://www.castleproject.org/
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 namespace Castle.Monorail.JSONSupport
17 using System;
18 using System.Reflection;
19 using Castle.MonoRail.Framework;
20 using Newtonsoft.Json;
22 /// <summary>
23 /// Extends <see cref="DataBindAttribute"/> with the <see cref="JavaScriptConvert"/> functionality.
24 /// In other words, enable biding of JSON formatted values on POCO objects.
25 /// </summary>
26 /// <example>
27 /// <para>
28 /// The following demonstrates how to bind a JSON querystring value representing a Car object instance
29 /// to a POCO Car object instance:
30 /// </para>
31 /// The querystring:
32 /// <code>
33 /// car={Wheels=4,Year=2007,Model='Cheap'}
34 /// </code>
35 /// And you want to bind those values to a instance of yours Car class, which looks like this:
36 /// <code>
37 /// public class Car
38 /// {
39 /// private int wheels, year;
40 /// private string model;
41 ///
42 /// public int Wheels
43 /// {
44 /// get { return wheels; }
45 /// set { wheels = value; }
46 /// }
47 ///
48 /// public int Year
49 /// {
50 /// get { return year; }
51 /// set { year = value; }
52 /// }
53 ///
54 /// public string Model
55 /// {
56 /// get { return model; }
57 /// set { model = value; }
58 /// }
59 /// }
60 /// </code>
61 /// <para>Using the <see cref="JSONBinderAttribute"/> and the <see cref="SmartDispatcherController"/>, all you have to
62 /// do is to mark the method parameter with the attribute, like the following example:</para>
63 /// <code>
64 /// public void MyAction([JSONBinder("car")] Car car)
65 /// </code>
66 /// </example>
67 [AttributeUsage(AttributeTargets.Parameter)]
68 public class JSONBinderAttribute : Attribute, IParameterBinder
70 private readonly string entryKey;
72 /// <summary>
73 /// Initializes a new instance of the <see cref="JSONBinderAttribute"/> class.
74 /// For use with <see cref="Castle.MonoRail.Framework.Helpers.AjaxHelper.GenerateJSProxy(string)" />,
75 /// make sure you are using Prototype 1.5.1 or later.
76 /// </summary>
77 /// <param name="entryKey">The entry key, which is the form or
78 /// querystring key that identifies the JSON persisted content</param>
79 public JSONBinderAttribute(string entryKey)
81 if (entryKey == null) throw new ArgumentNullException("entryKey");
83 this.entryKey = entryKey;
86 /// <summary>
87 /// Gets the entry key.
88 /// </summary>
89 /// <remarks>
90 /// The entry key, which is the form or querystring key that identifies the JSON persisted content.
91 /// </remarks>
92 /// <value>The entry key.</value>
93 public string EntryKey
95 get { return this.entryKey; }
98 /// <summary>
99 /// Calculates the param points. Implementors should return value equals or greater than
100 /// zero indicating whether the parameter can be bound successfully. The greater the value (points)
101 /// the more successful the implementation indicates to the framework
102 /// </summary>
103 /// <param name="controller">The controller.</param>
104 /// <param name="parameterInfo">The parameter info.</param>
105 /// <returns></returns>
106 public int CalculateParamPoints(SmartDispatcherController controller, ParameterInfo parameterInfo)
108 return controller.Params[entryKey] != null ? 1 : 0;
111 /// <summary>
112 /// Binds the specified parameter for the action.
113 /// </summary>
114 /// <param name="controller">The controller.</param>
115 /// <param name="parameterInfo">The parameter info.</param>
116 /// <returns>A instance based on the JSON values present in the <see cref="EntryKey"/>.</returns>
117 public object Bind(SmartDispatcherController controller, ParameterInfo parameterInfo)
119 string entryValue = controller.Params[entryKey];
121 return Bind(entryValue, parameterInfo.ParameterType);
124 /// <summary>
125 /// Binds the specified entry value to a instance of a given Type(<paramref name="parameterType"/>).
126 /// </summary>
127 /// <param name="entryValue">The entry value containing the JSON formatted content.</param>
128 /// <param name="parameterType">Type of the binded object.</param>
129 /// <returns>A instance based on the JSON values present in the <paramref name="entryValue"/>.</returns>
130 public static object Bind(string entryValue, Type parameterType)
132 return JavaScriptConvert.DeserializeObject(entryValue, parameterType);