Author: Andrew Davey
(2009/09/01 13:40) Over 2 years ago
1
using System.Web.Mvc;
2
using Snooze;
3
using Snooze.Authentication;
4
5
namespace SampleApplication.Controllers
6
{
...
12
11
13
return OK(new HomeViewModel
14
15
Login = new LoginUrl(),
16
BooksLink = new BooksUrl().ToString()
17
}).WithXrdsHeader(); // for openid 2.0 support
});
18
}
19
20
using System.Web.Routing;
using SampleApplication.Controllers;
using Snooze.Routing;
7
namespace SampleApplication
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
// Snooze provides some handy features...
routes.AddOpenIdSupport();
routes.AddVersionedStaticFilesSupport();
routes.AddIE6Support();
86
_errorMessages.Add(message);
87
88
89
public override string ToString()
90
91
if (HasValue)
92
93
return Value.ToString();
94
95
else
96
97
return default(T).ToString();
98
99
100
public static implicit operator T(Input<T> input)
101
102
if (input.IsValid)
103
using System.ComponentModel;
using System.Web.Mvc;
using System;
namespace Snooze
public class InputModelBinder : DefaultModelBinder
8
9
public InputModelBinder(IModelBinder defaultBinder)
10
_innerBinder = defaultBinder;
IModelBinder _innerBinder;
protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor)
if (typeof(IInput).IsAssignableFrom(propertyDescriptor.PropertyType))
var binder = this.Binders.GetBinder(propertyDescriptor.PropertyType);
BindInputProperty(controllerContext, bindingContext, propertyDescriptor);
var context = new ModelBindingContext
ModelState = bindingContext.ModelState,
ModelType = propertyDescriptor.PropertyType,
ValueProvider = bindingContext.ValueProvider
};
var input = binder.BindModel(controllerContext, context);
SetProperty(controllerContext, bindingContext, propertyDescriptor, input);
21
22
23
24
base.BindProperty(controllerContext, bindingContext, propertyDescriptor);
25
26
27
28
void BindInputProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor)
29
30
31
if (binder is InputModelBinder) binder = _innerBinder;
32
33
34
35
ModelName = propertyDescriptor.Name,
36
37
ModelType = typeof(string),
38
39
40
var value = (string)binder.BindModel(controllerContext, context);
41
var input = (IInput)Activator.CreateInstance(propertyDescriptor.PropertyType);
42
if (value != null)
43
44
input.RawValue = value;
45
46
47
48
49
public interface IResourceFormatter
bool CanFormat(object resource, string mimeType);
bool CanFormat(ControllerContext context, object resource, string mimeType);
void Output(ControllerContext context, object resource, string contentType);
public class JsonFormatter : IResourceFormatter
public bool CanFormat(object resource, string mimeType)
public bool CanFormat(ControllerContext context, object resource, string mimeType)
return resource != null && mimeType == "application/json";
return new ResourceResult(304, null);
public virtual ActionResult Redirect(Url url)
return Redirect(url.ToString());
50
51
52
public virtual ActionResult TemporaryRedirect(Url url)
53
54
return new ResourceResult(307, url.ToString()).WithHeader("Location", url.ToString());
55
56
57
public virtual ActionResult TemporaryRedirect(string url)
58
59
return new ResourceResult(307, url).WithHeader("Location", url);
60
61
public virtual ResourceResult BadRequest()
62
63
return new ResourceResult(403, null);
64
return new ResourceResult(400, null);
65
66
public virtual ResourceResult BadRequest(object errorResource)
67
68
return new ResourceResult(403, errorResource);
69
return new ResourceResult(400, errorResource);
70
71
public virtual ResourceResult NotFound()
72
// So we add an explicitly typed ViewFormatter first.
_formatters.Add(new ViewFormatter("application/xhtml+xml"));
_formatters.Add(new ViewFormatter("*/*")); // similar reason for this.
_formatters.Add(new StringFormatter());
_formatters.Add(new JsonFormatter());
_formatters.Add(new XmlFormatter());
_formatters.Add(new ViewFormatter());
public static IList<IResourceFormatter> Formatters
82
83
84
var acceptTypes = ParseAcceptTypes(context.HttpContext.Request.AcceptTypes);
85
var formatter = FindFormatter(acceptTypes);
var formatter = FindFormatter(context, acceptTypes);
if (formatter == null)
context.HttpContext.Response.StatusCode = 406; // not acceptable
if (Resource is string)
context.HttpContext.Response.Output.Write(Resource);
return;
formatter.Output(context, Resource, ContentType);
125
132
126
133
127
134
128
IResourceFormatter FindFormatter(IEnumerable<string> acceptTypes)
135
IResourceFormatter FindFormatter(ControllerContext context, IEnumerable<string> acceptTypes)
129
136
130
if (ContentType != null) // Controller action forced the content type.
137
131
138
EnsureContentTypeIsMimeType();
139
return ResourceFormatters.Formatters.FirstOrDefault(f => f.CanFormat(Resource, ContentType));
140
return ResourceFormatters.Formatters.FirstOrDefault(f => f.CanFormat(context, Resource, ContentType));
141
142
foreach (var formatter in ResourceFormatters.Formatters)
143
144
foreach (var acceptType in acceptTypes)
145
146
if (formatter.CanFormat(Resource, acceptType)) return formatter;
147
if (formatter.CanFormat(context, Resource, acceptType)) return formatter;
148
149
return null;
150
<Compile Include="FutureAction.cs" />
<Compile Include="IInput.cs" />
<Compile Include="Input.cs" />
<Compile Include="InputModelAttribute.cs" />
<Compile Include="InputModelBinder.cs" />
<Compile Include="IResourceFormatter.cs" />
<Compile Include="JsonFormatter.cs" />
public class StringFormatter : IResourceFormatter
if (resource != null && resource.GetType() == typeof(string)) return true;
if (mimeType == "text/plain") return true;
string _targetMimeType;
return (_targetMimeType == mimeType) || (_targetMimeType == null);
return ((_targetMimeType == mimeType) || (_targetMimeType == null))
&& FindView(context, resource).View != null;
public void Output(ControllerContext context, object resource, string contentType)
if (contentType != null)
context.HttpContext.Response.ContentType = contentType;
var result = FindView(context, resource);
if (result.View != null)
result.View.Render(
new ViewContext(
context,
result.View,
new ViewDataDictionary(resource),
new TempDataDictionary()
),
context.HttpContext.Response.Output
);
private ViewEngineResult FindView(ControllerContext context, object resource)
var viewName = GetViewName(resource);
var result = ViewEngines.Engines.FindView(context, viewName, null);
return result;
string GetViewName(object resource)
public class XmlFormatter : IResourceFormatter
return resource != null && mimeType.Contains("xml");
using Snooze.Authentication;{{{{{{Login = new LoginUrl(),}).WithXrdsHeader(); // for openid 2.0 support});using Snooze.Authentication;routes.IgnoreRoute("{resource}.axd/{*pathInfo}");routes.IgnoreRoute("{resource}.axd/{*pathInfo}");routes.AddOpenIdSupport();{{{{{{{{{{{{{{var binder = this.Binders.GetBinder(propertyDescriptor.PropertyType);BindInputProperty(controllerContext, bindingContext, propertyDescriptor);var context = new ModelBindingContext{ModelState = bindingContext.ModelState,ModelType = propertyDescriptor.PropertyType,ValueProvider = bindingContext.ValueProvider};var input = binder.BindModel(controllerContext, context);SetProperty(controllerContext, bindingContext, propertyDescriptor, input);{{{{{{{{{bool CanFormat(ControllerContext context, object resource, string mimeType);{{{{public bool CanFormat(ControllerContext context, object resource, string mimeType){{{{return new ResourceResult(307, url.ToString()).WithHeader("Location", url.ToString());{return new ResourceResult(307, url).WithHeader("Location", url);{{return new ResourceResult(403, null);return new ResourceResult(400, null);{{return new ResourceResult(403, errorResource);return new ResourceResult(400, errorResource);_formatters.Add(new ViewFormatter("application/xhtml+xml"));_formatters.Add(new ViewFormatter("application/xhtml+xml"));_formatters.Add(new ViewFormatter("*/*")); // similar reason for this._formatters.Add(new ViewFormatter("*/*")); // similar reason for this._formatters.Add(new StringFormatter());var formatter = FindFormatter(context, acceptTypes);{{context.HttpContext.Response.StatusCode = 406; // not acceptableif (Resource is string){context.HttpContext.Response.Output.Write(Resource);}else{context.HttpContext.Response.StatusCode = 406; // not acceptable}IResourceFormatter FindFormatter(ControllerContext context, IEnumerable<string> acceptTypes){{{{return ResourceFormatters.Formatters.FirstOrDefault(f => f.CanFormat(context, Resource, ContentType));{{{{if (formatter.CanFormat(context, Resource, acceptType)) return formatter;<Compile Include="InputModelAttribute.cs" />{{{{public bool CanFormat(ControllerContext context, object resource, string mimeType){{public bool CanFormat(ControllerContext context, object resource, string mimeType){{return (_targetMimeType == mimeType) || (_targetMimeType == null);return ((_targetMimeType == mimeType) || (_targetMimeType == null))&& FindView(context, resource).View != null;{{{{{context.HttpContext.Response.ContentType = contentType;return result;result.View.Render(new ViewContext(context,result.View,new ViewDataDictionary(resource),new TempDataDictionary()),context.HttpContext.Response.Output);{{{{public bool CanFormat(ControllerContext context, object resource, string mimeType){{return resource != null && mimeType.Contains("xml");return resource != null && mimeType.Contains("xml");