1 // Copyright 2004-2007 Castle Project - http://www.castleproject.org/
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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
.Framework
18 using System
.Reflection
;
20 using Castle
.Components
.Binder
;
23 /// Defines where the parameters should be obtained from
25 public enum ParamStore
32 /// Only from the Form
36 /// From QueryString, Form and Environment variables.
42 /// The DataBind Attribute is used to indicate that an Action methods parameter
43 /// is to be intercepted and handled by the <see cref="Castle.Components.Binder.DataBinder"/>.
46 /// Allowed usage is one per method parameter, and is not inherited.
48 [AttributeUsage(AttributeTargets
.Parameter
, AllowMultiple
=false, Inherited
=false)]
49 public class DataBindAttribute
: Attribute
, IParameterBinder
51 private ParamStore
from = ParamStore
.Params
;
52 private string exclude
= string.Empty
;
53 private string allow
= string.Empty
;
54 private string prefix
;
55 private bool validate
;
58 /// Creates a <see cref="DataBindAttribute"/>
59 /// with an associated prefix. The prefix must be present
60 /// in the form data and is used to avoid name clashes.
62 /// <param name="prefix"></param>
63 public DataBindAttribute(string prefix
)
69 /// Gets or sets the property names to exclude.
71 /// <remarks>The property name should include the <i>prefix</i>.</remarks>
72 /// <value>A comma separated list
73 /// of property names to exclude from databinding.</value>
76 get { return exclude; }
77 set { exclude = value; }
81 /// Gets or sets the property names to allow.
83 /// <remarks>The property name should include the <i>prefix</i>.</remarks>
84 /// <value>A comma separated list
85 /// of property names to allow from databinding.</value>
89 set { allow = value; }
93 /// Gets or sets a value indicating whether
94 /// the target should be validate during binding.
96 /// <value><c>true</c> if should be validated; otherwise, <c>false</c>.</value>
99 get { return validate; }
100 set { validate = value; }
104 /// Gets or sets <see cref="ParamStore"/> used to
105 /// indicate where to get the values from
107 /// <value>The <see cref="ParamStore"/> type.
108 /// Typically <see cref="ParamStore.Params"/>.</value>
109 public ParamStore From
112 set { from = value; }
116 /// Gets the databinding prefix.
119 /// The prefix is a name followed by a
120 /// dot that prefixes the entries names
121 /// on the source http request.
123 /// <value>The databinding prefix.</value>
126 get { return prefix; }
130 /// Implementation of <see cref="IParameterBinder.CalculateParamPoints"/>
131 /// and it is used to give the method a weight when overloads are available.
133 /// <param name="controller">The controller instance</param>
134 /// <param name="parameterInfo">The parameter info</param>
135 /// <returns>Positive value if the parameter can be bound</returns>
136 public int CalculateParamPoints(SmartDispatcherController controller
, ParameterInfo parameterInfo
)
138 CompositeNode node
= controller
.ObtainParamsNode(From
);
140 IDataBinder binder
= CreateBinder();
142 return binder
.CanBindObject(parameterInfo
.ParameterType
, prefix
, node
) ? 10 : 0;
146 /// Implementation of <see cref="IParameterBinder.Bind"/>
147 /// and it is used to read the data available and construct the
148 /// parameter type accordingly.
150 /// <param name="controller">The controller instance</param>
151 /// <param name="parameterInfo">The parameter info</param>
152 /// <returns>The bound instance</returns>
153 public virtual object Bind(SmartDispatcherController controller
, ParameterInfo parameterInfo
)
155 IDataBinder binder
= CreateBinder();
157 ConfigureValidator(controller
, binder
);
159 CompositeNode node
= controller
.ObtainParamsNode(From
);
161 object instance
= binder
.BindObject(parameterInfo
.ParameterType
, prefix
, exclude
, allow
, node
);
163 BindInstanceErrors(controller
, binder
, instance
);
164 PopulateValidatorErrorSummary(controller
, binder
, instance
);
170 /// Creates the binder.
172 /// <returns></returns>
173 protected virtual IDataBinder
CreateBinder()
175 return new DataBinder();
179 /// Configures the validator.
181 /// <param name="controller">The controller.</param>
182 /// <param name="binder">The binder.</param>
183 protected void ConfigureValidator(SmartDispatcherController controller
, IDataBinder binder
)
187 binder
.Validator
= controller
.Validator
;
191 binder
.Validator
= null;
196 /// Populates the validator error summary.
198 /// <param name="controller">The controller.</param>
199 /// <param name="binder">The binder.</param>
200 /// <param name="instance">The instance.</param>
201 protected void PopulateValidatorErrorSummary(SmartDispatcherController controller
, IDataBinder binder
, object instance
)
205 controller
.PopulateValidatorErrorSummary(instance
, binder
);
210 /// Binds the instance errors.
212 /// <param name="controller">The controller.</param>
213 /// <param name="binder">The binder.</param>
214 /// <param name="instance">The instance.</param>
215 protected void BindInstanceErrors(SmartDispatcherController controller
, IDataBinder binder
, object instance
)
217 if (instance
!= null)
219 controller
.BoundInstanceErrors
[instance
] = binder
.ErrorList
;