Fixing an issue with output parameters that are of type IntPtr
[castle.git] / MonoRail / Castle.MonoRail.Framework / Attributes / JSONReturnBinderAttribute.cs
blob16b1b33ca3e774e25d1ded195ee57bdc36014b95
1 // Copyright 2004-2008 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.Framework
17 using System;
18 using System.Collections.Generic;
19 using System.Reflection;
20 using Services;
22 /// <summary>
23 /// Pendent
24 /// </summary>
25 [AttributeUsage(AttributeTargets.ReturnValue, AllowMultiple = false, Inherited = false)]
26 public class JSONReturnBinderAttribute : Attribute, IReturnBinder
28 private string properties;
30 /// <summary>
31 /// Gets or sets the properties to be serialized.
32 /// </summary>
33 /// <value>The properties.</value>
34 public string Properties
36 get { return properties; }
37 set { properties = value; }
40 /// <summary>
41 /// Binds the specified parameters for the action.
42 /// </summary>
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)
65 // Sets the mime type
66 response.ContentType = "application/json, text/javascript";
69 string raw;
71 if (returnValue != null)
73 if (properties == null)
75 raw = serializer.Serialize(returnValue);
77 else
79 Type normalized = returnType.IsArray ? returnType.GetElementType() : returnType;
81 raw = serializer.Serialize(returnValue, new PropertyConverter(normalized, properties));
84 else
86 if (returnType.IsArray)
88 raw = "[]";
90 else
92 raw = "{}";
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);
112 if (prop == null)
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;
142 #if DOTNET35
143 public object ReadJson(IJSONReader reader, Type objectType)
145 throw new NotImplementedException();
147 #endif