1
// Copyright 2004-2008 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
.Collections
.Generic
;
19 using System
.Reflection
;
25 [AttributeUsage(AttributeTargets
.ReturnValue
, AllowMultiple
= false, Inherited
= false)]
26 public class JSONReturnBinderAttribute
: Attribute
, IReturnBinder
28 private string properties
;
31 /// Gets or sets the properties to be serialized.
33 /// <value>The properties.</value>
34 public string Properties
36 get { return properties; }
37 set { properties = value; }
41 /// Binds the specified parameters for the action.
43 /// <param name="context">The context.</param>
44 /// <param name="controller">The controller.</param>
45 /// <param name="controllerContext">The controller context.</param>
46 /// <param name="returnType">Type being returned.</param>
47 /// <param name="returnValue">The return value.</param>
48 /// <returns></returns>
49 public void Bind(IEngineContext context
, IController controller
, IControllerContext controllerContext
,
50 Type returnType
, object returnValue
)
52 // Cancel any view rendering
53 controllerContext
.SelectedViewName
= null;
55 IJSONSerializer serializer
= context
.Services
.JSONSerializer
;
57 IResponse response
= context
.Response
;
59 string userAgent
= context
.Request
.Headers
["User-Agent"];
61 // Ridiculous hack, but necessary. If we set the mime type for mobile clients, they
62 // will treat the response as binary!!
63 if (userAgent
!= null && userAgent
.IndexOf("Windows CE") == -1)
66 response
.ContentType
= "application/json, text/javascript";
71 if (returnValue
!= null)
73 if (properties
== null)
75 raw
= serializer
.Serialize(returnValue
);
79 Type normalized
= returnType
.IsArray
? returnType
.GetElementType() : returnType
;
81 raw
= serializer
.Serialize(returnValue
, new PropertyConverter(normalized
, properties
));
86 if (returnType
.IsArray
)
96 response
.Output
.Write(raw
);
99 class PropertyConverter
: IJSONConverter
101 private readonly Type targetType
;
102 private List
<PropertyInfo
> properties
= new List
<PropertyInfo
>();
104 public PropertyConverter(Type targetType
, string propertyNames
)
106 this.targetType
= targetType
;
108 foreach(string propertyName
in propertyNames
.Split(','))
110 PropertyInfo prop
= targetType
.GetProperty(propertyName
);
114 throw new MonoRailException("Failed to JSON serialize object. " +
115 "Property " + propertyName
+ " could not be found for type " + targetType
.FullName
);
118 properties
.Add(prop
);
122 public void Write(IJSONWriter writer
, object value)
124 writer
.WriteStartObject();
126 foreach(PropertyInfo info
in properties
)
128 object propVal
= info
.GetValue(value, null);
130 writer
.WritePropertyName(info
.Name
);
131 writer
.WriteValue(propVal
);
134 writer
.WriteEndObject();
137 public bool CanHandle(Type type
)
139 return type
== targetType
;
143 public object ReadJson(IJSONReader reader
, Type objectType
)
145 throw new NotImplementedException();