diff --git a/Microsoft.AspNet.Mvc/ActionResults/NoContentResult.cs b/Microsoft.AspNet.Mvc/ActionResults/NoContentResult.cs
new file mode 100644
index 0000000000..4ba37f566e
--- /dev/null
+++ b/Microsoft.AspNet.Mvc/ActionResults/NoContentResult.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.Owin;
+using System.Net;
+
+namespace Microsoft.AspNet.Mvc
+{
+ public class NoContentResult : IActionResult
+ {
+ public async Task ExecuteResultAsync(RequestContext context)
+ {
+ if (context == null)
+ {
+ throw new ArgumentNullException("context");
+ }
+
+ IOwinResponse response = context.HttpContext.Response;
+
+ response.StatusCode = (int)HttpStatusCode.NoContent;
+
+ await Task.FromResult(false);
+
+ return;
+ }
+ }
+}
diff --git a/Microsoft.AspNet.Mvc/ActionResults/ObjectContent.cs b/Microsoft.AspNet.Mvc/ActionResults/ObjectContent.cs
new file mode 100644
index 0000000000..931b7b7c3f
--- /dev/null
+++ b/Microsoft.AspNet.Mvc/ActionResults/ObjectContent.cs
@@ -0,0 +1,159 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+using System;
+using System.Diagnostics.Contracts;
+using System.IO;
+using System.Net.Http;
+using System.Net.Http.Formatting;
+using System.Net.Http.Headers;
+using System.Threading.Tasks;
+using System.Web.Http;
+
+namespace Microsoft.AspNet.Mvc
+{
+ ///
+ /// Contains a value as well as an associated that will be
+ /// used to serialize the value when writing this content.
+ ///
+ public class ObjectContent : HttpContent
+ {
+ private object _value;
+ private readonly MediaTypeFormatter _formatter;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The type of object this instance will contain.
+ /// The value of the object this instance will contain.
+ /// The formatter to use when serializing the value.
+ public ObjectContent(Type type, object value, MediaTypeFormatter formatter)
+ : this(type, value, formatter, (MediaTypeHeaderValue)null)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The type of object this instance will contain.
+ /// The value of the object this instance will contain.
+ /// The formatter to use when serializing the value.
+ /// The authoritative value of the content's Content-Type header. Can be null in which case the
+ /// formatter's default content type will be used.
+ public ObjectContent(Type type, object value, MediaTypeFormatter formatter, string mediaType)
+ : this(type, value, formatter, BuildHeaderValue(mediaType))
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The type of object this instance will contain.
+ /// The value of the object this instance will contain.
+ /// The formatter to use when serializing the value.
+ /// The authoritative value of the content's Content-Type header. Can be null in which case the
+ /// formatter's default content type will be used.
+ public ObjectContent(Type type, object value, MediaTypeFormatter formatter, MediaTypeHeaderValue mediaType)
+ {
+ if (type == null)
+ {
+ throw new ArgumentNullException("type");
+ }
+ if (formatter == null)
+ {
+ throw new ArgumentNullException("formatter");
+ }
+
+ if (!formatter.CanWriteType(type))
+ {
+ throw new ArgumentNullException(formatter.GetType().FullName + " cannot write " + type.Name);
+ }
+
+ _formatter = formatter;
+ ObjectType = type;
+
+ VerifyAndSetObject(value);
+ _formatter.SetDefaultContentHeaders(type, Headers, mediaType);
+ }
+
+ ///
+ /// Gets the type of object managed by this instance.
+ ///
+ public Type ObjectType { get; private set; }
+
+ ///
+ /// The formatter associated with this content instance.
+ ///
+ public MediaTypeFormatter Formatter
+ {
+ get { return _formatter; }
+ }
+
+ ///
+ /// Gets or sets the value of the current .
+ ///
+ public object Value
+ {
+ get { return _value; }
+ set { _value = value; }
+ }
+
+ internal static MediaTypeHeaderValue BuildHeaderValue(string mediaType)
+ {
+ return mediaType != null ? new MediaTypeHeaderValue(mediaType) : null;
+ }
+
+ ///
+ /// Asynchronously serializes the object's content to the given .
+ ///
+ /// The to which to write.
+ /// The associated .
+ /// A instance that is asynchronously serializing the object's content.
+ protected override Task SerializeToStreamAsync(Stream stream, System.Net.TransportContext context)
+ {
+ return _formatter.WriteToStreamAsync(ObjectType, Value, stream, this, context);
+ }
+
+ ///
+ /// Computes the length of the stream if possible.
+ ///
+ /// The computed length of the stream.
+ /// true if the length has been computed; otherwise false.
+ protected override bool TryComputeLength(out long length)
+ {
+ length = -1;
+ return false;
+ }
+
+ private static bool IsTypeNullable(Type type)
+ {
+ return !type.IsValueType() ||
+ (type.IsGenericType() &&
+ type.GetGenericTypeDefinition() == typeof(Nullable<>));
+ }
+
+ private void VerifyAndSetObject(object value)
+ {
+ Contract.Assert(ObjectType != null, "Type cannot be null");
+
+ if (value == null)
+ {
+ // Null may not be assigned to value types (unless Nullable)
+ if (!IsTypeNullable(ObjectType))
+ {
+ throw new InvalidOperationException("CannotUseNullValueType " + typeof(ObjectContent).Name + " " + ObjectType.Name);
+ }
+ }
+ else
+ {
+ // Non-null objects must be a type assignable to Type
+ Type objectType = value.GetType();
+ if (!ObjectType.IsAssignableFrom(objectType))
+ {
+ throw new ArgumentException("value Resources.ObjectAndTypeDisagree, objectType.Name, ObjectType.Name");
+ }
+ }
+
+ _value = value;
+ }
+ }
+}
diff --git a/Microsoft.AspNet.Mvc/DefaultContentNegotiator.cs b/Microsoft.AspNet.Mvc/DefaultContentNegotiator.cs
new file mode 100644
index 0000000000..ae70031539
--- /dev/null
+++ b/Microsoft.AspNet.Mvc/DefaultContentNegotiator.cs
@@ -0,0 +1,599 @@
+//// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+using Microsoft.Owin;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics.Contracts;
+using System.Linq;
+using System.Net.Http;
+using System.Net.Http.Formatting;
+using System.Net.Http.Headers;
+using System.Text;
+using System.Web.Http;
+
+namespace Microsoft.AspNet.Mvc
+{
+ ///
+ /// Class that selects a for an
+ /// or .
+ ///
+ public class DefaultContentNegotiator : IOwinContentNegotiator
+ {
+// public DefaultContentNegotiator()
+// : this(false)
+// {
+// }
+
+// ///
+// /// Initializes a new instance of the with
+// /// the given setting for .
+// ///
+// ///
+// /// If ExcludeMatchOnTypeOnly is true then we don't match on type only which means
+// /// that we return null if we can't match on anything in the request. This is useful
+// /// for generating 406 (Not Acceptable) status codes.
+// ///
+// public DefaultContentNegotiator(bool excludeMatchOnTypeOnly)
+// {
+// ExcludeMatchOnTypeOnly = excludeMatchOnTypeOnly;
+// }
+
+// ///
+// /// If ExcludeMatchOnTypeOnly is true then we don't match on type only which means
+// /// that we return null if we can't match on anything in the request. This is useful
+// /// for generating 406 (Not Acceptable) status codes.
+// ///
+// public bool ExcludeMatchOnTypeOnly { get; private set; }
+
+// ///
+// /// Performs content negotiating by selecting the most appropriate out of the passed in
+// /// for the given that can serialize an object of the given
+// /// .
+// ///
+// /// The type to be serialized.
+// /// The request.
+// /// The set of objects from which to choose.
+// /// The result of the negotiation containing the most appropriate instance,
+// /// or null if there is no appropriate formatter.
+// public virtual ContentNegotiationResult Negotiate(Type type, IOwinContext context, IEnumerable formatters)
+// {
+// // Performance-sensitive
+// if (type == null)
+// {
+// throw new ArgumentNullException("type");
+// }
+// if (context == null)
+// {
+// throw new ArgumentNullException("context");
+// }
+// if (formatters == null)
+// {
+// throw new ArgumentNullException("formatters");
+// }
+
+// var request = context.Request;
+
+// // Go through each formatter to compute how well it matches.
+// Collection matches = ComputeFormatterMatches(type, request, formatters);
+
+// // Select best formatter match among the matches
+// MediaTypeFormatterMatch bestFormatterMatch = SelectResponseMediaTypeFormatter(matches);
+
+// // We found a best formatter
+// if (bestFormatterMatch != null)
+// {
+// // Find the best character encoding for the selected formatter
+// Encoding bestEncodingMatch = SelectResponseCharacterEncoding(request, bestFormatterMatch.Formatter);
+// if (bestEncodingMatch != null)
+// {
+// bestFormatterMatch.MediaType.CharSet = bestEncodingMatch.WebName;
+// }
+
+// MediaTypeHeaderValue bestMediaType = bestFormatterMatch.MediaType;
+// MediaTypeFormatter bestFormatter = bestFormatterMatch.Formatter; // this is OData only scenario at the moment: .GetPerRequestFormatterInstance(type, request, bestMediaType);
+// return new ContentNegotiationResult(bestFormatter, bestMediaType);
+// }
+
+// return null;
+// }
+
+// ///
+// /// Determine how well each formatter matches by associating a value
+// /// with the formatter. Then associate the quality of the match based on q-factors and other parameters. The result of this
+// /// method is a collection of the matches found categorized and assigned a quality value.
+// ///
+// /// The type to be serialized.
+// /// The request.
+// /// The set of objects from which to choose.
+// /// A collection containing all the matches.
+// protected virtual Collection ComputeFormatterMatches(Type type, IOwinRequest request, IEnumerable formatters)
+// {
+// // Performance-sensitive
+// if (type == null)
+// {
+// throw new ArgumentNullException("type");
+// }
+// if (request == null)
+// {
+// throw new ArgumentNullException("request");
+// }
+// if (formatters == null)
+// {
+// throw new ArgumentNullException("formatters");
+// }
+
+// IEnumerable sortedAcceptValues = null;
+
+// // Go through each formatter to find how well it matches.
+// List matches = new List();
+// MediaTypeFormatter[] writingFormatters = GetWritingFormatters(formatters);
+// for (int i = 0; i < writingFormatters.Length; i++)
+// {
+// MediaTypeFormatter formatter = writingFormatters[i];
+// MediaTypeFormatterMatch match = null;
+
+// // Check first that formatter can write the actual type
+// if (!formatter.CanWriteType(type))
+// {
+// // Formatter can't even write the type so no match at all
+// continue;
+// }
+
+// // Match against media type mapping.
+// if ((match = MatchMediaTypeMapping(request, formatter)) != null)
+// {
+// matches.Add(match);
+// continue;
+// }
+
+// // Match against the accept header values.
+// if (sortedAcceptValues == null)
+// {
+// // Sort the Accept header values in descending order based on q-factor
+// sortedAcceptValues = SortMediaTypeWithQualityHeaderValuesByQFactor(request.Headers.Accept);
+// }
+// if ((match = MatchAcceptHeader(sortedAcceptValues, formatter)) != null)
+// {
+// matches.Add(match);
+// continue;
+// }
+
+// // Match against request's media type if any
+// if ((match = MatchRequestMediaType(request, formatter)) != null)
+// {
+// matches.Add(match);
+// continue;
+// }
+
+// // Check whether we should match on type or stop the matching process.
+// // The latter is used to generate 406 (Not Acceptable) status codes.
+// bool shouldMatchOnType = ShouldMatchOnType(sortedAcceptValues);
+
+// // Match against the type of object we are writing out
+// if (shouldMatchOnType && (match = MatchType(type, formatter)) != null)
+// {
+// matches.Add(match);
+// continue;
+// }
+// }
+
+// return matches;
+// }
+
+// ///
+// /// Select the best match among the candidate matches found.
+// ///
+// /// The collection of matches.
+// /// The determined to be the best match.
+// protected virtual MediaTypeFormatterMatch SelectResponseMediaTypeFormatter(ICollection matches)
+// {
+// // Performance-sensitive
+// if (matches == null)
+// {
+// throw new ArgumentNullException("matches");
+// }
+
+// List matchList = matches.AsList();
+
+// MediaTypeFormatterMatch bestMatchOnType = null;
+// MediaTypeFormatterMatch bestMatchOnAcceptHeaderLiteral = null;
+// MediaTypeFormatterMatch bestMatchOnAcceptHeaderSubtypeMediaRange = null;
+// MediaTypeFormatterMatch bestMatchOnAcceptHeaderAllMediaRange = null;
+// MediaTypeFormatterMatch bestMatchOnMediaTypeMapping = null;
+// MediaTypeFormatterMatch bestMatchOnRequestMediaType = null;
+
+// // Go through each formatter to find the best match in each category.
+// for (int i = 0; i < matchList.Count; i++)
+// {
+// MediaTypeFormatterMatch match = matchList[i];
+// switch (match.Ranking)
+// {
+// case MediaTypeFormatterMatchRanking.MatchOnCanWriteType:
+// // First match by type trumps all other type matches
+// if (bestMatchOnType == null)
+// {
+// bestMatchOnType = match;
+// }
+// break;
+
+// case MediaTypeFormatterMatchRanking.MatchOnRequestWithMediaTypeMapping:
+// // Matches on accept headers using mappings must choose the highest quality match
+// bestMatchOnMediaTypeMapping = UpdateBestMatch(bestMatchOnMediaTypeMapping, match);
+// break;
+
+// case MediaTypeFormatterMatchRanking.MatchOnRequestAcceptHeaderLiteral:
+// // Matches on accept headers must choose the highest quality match.
+// // A match of 0.0 means we won't use it at all.
+// bestMatchOnAcceptHeaderLiteral = UpdateBestMatch(bestMatchOnAcceptHeaderLiteral, match);
+// break;
+
+// case MediaTypeFormatterMatchRanking.MatchOnRequestAcceptHeaderSubtypeMediaRange:
+// // Matches on accept headers must choose the highest quality match.
+// // A match of 0.0 means we won't use it at all.
+// bestMatchOnAcceptHeaderSubtypeMediaRange = UpdateBestMatch(bestMatchOnAcceptHeaderSubtypeMediaRange, match);
+// break;
+
+// case MediaTypeFormatterMatchRanking.MatchOnRequestAcceptHeaderAllMediaRange:
+// // Matches on accept headers must choose the highest quality match.
+// // A match of 0.0 means we won't use it at all.
+// bestMatchOnAcceptHeaderAllMediaRange = UpdateBestMatch(bestMatchOnAcceptHeaderAllMediaRange, match);
+// break;
+
+// case MediaTypeFormatterMatchRanking.MatchOnRequestMediaType:
+// // First match on request content type trumps other request content matches
+// if (bestMatchOnRequestMediaType == null)
+// {
+// bestMatchOnRequestMediaType = match;
+// }
+// break;
+// }
+// }
+
+// // If we received matches based on both supported media types and from media type mappings,
+// // we want to give precedence to the media type mappings, but only if their quality is >= that of the supported media type.
+// // We do this because media type mappings are the user's extensibility point and must take precedence over normal
+// // supported media types in the case of a tie. The 99% case is where both have quality 1.0.
+// if (bestMatchOnMediaTypeMapping != null)
+// {
+// MediaTypeFormatterMatch mappingOverride = bestMatchOnMediaTypeMapping;
+// mappingOverride = UpdateBestMatch(mappingOverride, bestMatchOnAcceptHeaderLiteral);
+// mappingOverride = UpdateBestMatch(mappingOverride, bestMatchOnAcceptHeaderSubtypeMediaRange);
+// mappingOverride = UpdateBestMatch(mappingOverride, bestMatchOnAcceptHeaderAllMediaRange);
+// if (mappingOverride != bestMatchOnMediaTypeMapping)
+// {
+// bestMatchOnMediaTypeMapping = null;
+// }
+// }
+
+// // now select the formatter and media type
+// // A MediaTypeMapping is highest precedence -- it is an extensibility point
+// // allowing the user to override normal accept header matching
+// MediaTypeFormatterMatch bestMatch = null;
+// if (bestMatchOnMediaTypeMapping != null)
+// {
+// bestMatch = bestMatchOnMediaTypeMapping;
+// }
+// else if (bestMatchOnAcceptHeaderLiteral != null ||
+// bestMatchOnAcceptHeaderSubtypeMediaRange != null ||
+// bestMatchOnAcceptHeaderAllMediaRange != null)
+// {
+// bestMatch = UpdateBestMatch(bestMatch, bestMatchOnAcceptHeaderLiteral);
+// bestMatch = UpdateBestMatch(bestMatch, bestMatchOnAcceptHeaderSubtypeMediaRange);
+// bestMatch = UpdateBestMatch(bestMatch, bestMatchOnAcceptHeaderAllMediaRange);
+// }
+// else if (bestMatchOnRequestMediaType != null)
+// {
+// bestMatch = bestMatchOnRequestMediaType;
+// }
+// else if (bestMatchOnType != null)
+// {
+// bestMatch = bestMatchOnType;
+// }
+
+// return bestMatch;
+// }
+
+// ///
+// /// Determine the best character encoding for writing the response. First we look
+// /// for accept-charset headers and if not found then we try to match
+// /// any charset encoding in the request (in case of PUT, POST, etc.)
+// /// If no encoding is found then we use the default for the formatter.
+// ///
+// /// The determined to be the best match.
+// protected virtual Encoding SelectResponseCharacterEncoding(IOwinRequest request, MediaTypeFormatter formatter)
+// {
+// if (request == null)
+// {
+// throw new ArgumentNullException("request");
+// }
+// if (formatter == null)
+// {
+// throw new ArgumentNullException("formatter");
+// }
+
+// // If there are any SupportedEncodings then we pick an encoding
+// List supportedEncodings = formatter.SupportedEncodingsInternal;
+// if (supportedEncodings.Count > 0)
+// {
+// // Sort Accept-Charset header values
+// IEnumerable sortedAcceptCharsetValues = SortStringWithQualityHeaderValuesByQFactor(request.Headers.AcceptCharset);
+
+// // Check for match based on accept-charset headers
+// foreach (StringWithQualityHeaderValue acceptCharset in sortedAcceptCharsetValues)
+// {
+// for (int i = 0; i < supportedEncodings.Count; i++)
+// {
+// Encoding encoding = supportedEncodings[i];
+// if (encoding != null && acceptCharset.Quality != FormattingUtilities.NoMatch &&
+// (acceptCharset.Value.Equals(encoding.WebName, StringComparison.OrdinalIgnoreCase) ||
+// acceptCharset.Value.Equals("*", StringComparison.OrdinalIgnoreCase)))
+// {
+// return encoding;
+// }
+// }
+// }
+
+// // Check for match based on any request entity body
+
+// // TODO: Transform to use request content headers directly
+// // was - request.Content != null ? request.Content.Headers : null
+// return formatter.SelectCharacterEncoding(null);
+// }
+
+// return null;
+// }
+
+// ///
+// /// Match a request against the s registered with the formatter.
+// ///
+// /// The request to match.
+// /// The formatter to match against.
+// /// A indicating the quality of the match or null is no match.
+// protected virtual MediaTypeFormatterMatch MatchMediaTypeMapping(IOwinRequest request, MediaTypeFormatter formatter)
+// {
+// if (request == null)
+// {
+// throw new ArgumentNullException("request");
+// }
+// if (formatter == null)
+// {
+// throw new ArgumentNullException("formatter");
+// }
+
+// List mediaTypeMappings = formatter.MediaTypeMappingsInternal;
+// for (int i = 0; i < mediaTypeMappings.Count; i++)
+// {
+// MediaTypeMapping mapping = mediaTypeMappings[i];
+// double quality;
+// if (mapping != null && ((quality = mapping.TryMatchMediaType(request)) > FormattingUtilities.NoMatch))
+// {
+// return new MediaTypeFormatterMatch(formatter, mapping.MediaType, quality, MediaTypeFormatterMatchRanking.MatchOnRequestWithMediaTypeMapping);
+// }
+// }
+
+// return null;
+// }
+
+// ///
+// /// Match the request accept header field values against the formatter's registered supported media types.
+// ///
+// /// The sorted accept header values to match.
+// /// The formatter to match against.
+// /// A indicating the quality of the match or null is no match.
+// protected virtual MediaTypeFormatterMatch MatchAcceptHeader(IEnumerable sortedAcceptValues, MediaTypeFormatter formatter)
+// {
+// if (sortedAcceptValues == null)
+// {
+// throw Error.ArgumentNull("sortedAcceptValues");
+// }
+// if (formatter == null)
+// {
+// throw Error.ArgumentNull("formatter");
+// }
+
+// foreach (MediaTypeWithQualityHeaderValue acceptMediaTypeValue in sortedAcceptValues)
+// {
+// List supportedMediaTypes = formatter.SupportedMediaTypesInternal;
+// for (int i = 0; i < supportedMediaTypes.Count; i++)
+// {
+// MediaTypeHeaderValue supportedMediaType = supportedMediaTypes[i];
+// MediaTypeHeaderValueRange range;
+// if (supportedMediaType != null && acceptMediaTypeValue.Quality != FormattingUtilities.NoMatch &&
+// supportedMediaType.IsSubsetOf(acceptMediaTypeValue, out range))
+// {
+// MediaTypeFormatterMatchRanking ranking;
+// switch (range)
+// {
+// case MediaTypeHeaderValueRange.AllMediaRange:
+// ranking = MediaTypeFormatterMatchRanking.MatchOnRequestAcceptHeaderAllMediaRange;
+// break;
+
+// case MediaTypeHeaderValueRange.SubtypeMediaRange:
+// ranking = MediaTypeFormatterMatchRanking.MatchOnRequestAcceptHeaderSubtypeMediaRange;
+// break;
+
+// default:
+// ranking = MediaTypeFormatterMatchRanking.MatchOnRequestAcceptHeaderLiteral;
+// break;
+// }
+
+// return new MediaTypeFormatterMatch(formatter, supportedMediaType, acceptMediaTypeValue.Quality, ranking);
+// }
+// }
+// }
+
+// return null;
+// }
+
+// ///
+// /// Match any request media type (in case there is a request entity body) against the formatter's registered
+// /// media types.
+// ///
+// /// The request to match.
+// /// The formatter to match against.
+// /// A indicating the quality of the match or null is no match.
+// protected virtual MediaTypeFormatterMatch MatchRequestMediaType(IOwinRequest request, MediaTypeFormatter formatter)
+// {
+// if (request == null)
+// {
+// throw new ArgumentNullException("request");
+// }
+// if (formatter == null)
+// {
+// throw new ArgumentNullException("formatter");
+// }
+
+// if (request.Content != null)
+// {
+// MediaTypeHeaderValue requestMediaType = request.Content.Headers.ContentType;
+// if (requestMediaType != null)
+// {
+// List supportedMediaTypes = formatter.SupportedMediaTypesInternal;
+// for (int i = 0; i < supportedMediaTypes.Count; i++)
+// {
+// MediaTypeHeaderValue supportedMediaType = supportedMediaTypes[i];
+// if (supportedMediaType != null && supportedMediaType.IsSubsetOf(requestMediaType))
+// {
+// return new MediaTypeFormatterMatch(formatter, supportedMediaType, FormattingUtilities.Match, MediaTypeFormatterMatchRanking.MatchOnRequestMediaType);
+// }
+// }
+// }
+// }
+
+// return null;
+// }
+
+// ///
+// /// Determine whether to match on type or not. This is used to determine whether to
+// /// generate a 406 response or use the default media type formatter in case there
+// /// is no match against anything in the request. If ExcludeMatchOnTypeOnly is true
+// /// then we don't match on type unless there are no accept headers.
+// ///
+// /// The sorted accept header values to match.
+// /// True if not ExcludeMatchOnTypeOnly and accept headers with a q-factor bigger than 0.0 are present.
+// protected virtual bool ShouldMatchOnType(IEnumerable sortedAcceptValues)
+// {
+// if (sortedAcceptValues == null)
+// {
+// throw new ArgumentNullException("sortedAcceptValues");
+// }
+
+// return !(ExcludeMatchOnTypeOnly && sortedAcceptValues.Any());
+// }
+
+// ///
+// /// Pick the first supported media type and indicate we've matched only on type
+// ///
+// /// The type to be serialized.
+// /// The formatter we are matching against.
+// /// A indicating the quality of the match or null is no match.
+// protected virtual MediaTypeFormatterMatch MatchType(Type type, MediaTypeFormatter formatter)
+// {
+// // Performance-sensitive
+// if (type == null)
+// {
+// throw new ArgumentNullException("type");
+// }
+// if (formatter == null)
+// {
+// throw new ArgumentNullException("formatter");
+// }
+
+// // We already know that we do match on type -- otherwise we wouldn't even be called --
+// // so this is just a matter of determining how we match.
+// MediaTypeHeaderValue mediaType = null;
+// List supportedMediaTypes = formatter.SupportedMediaTypesInternal;
+// if (supportedMediaTypes.Count > 0)
+// {
+// mediaType = supportedMediaTypes[0];
+// }
+// return new MediaTypeFormatterMatch(formatter, mediaType, FormattingUtilities.Match, MediaTypeFormatterMatchRanking.MatchOnCanWriteType);
+// }
+
+// ///
+// /// Sort Accept header values and related header field values with similar syntax rules
+// /// (if more than 1) in descending order based on q-factor.
+// ///
+// /// The header values to sort.
+// /// The sorted header values.
+// protected virtual IEnumerable SortMediaTypeWithQualityHeaderValuesByQFactor(ICollection headerValues)
+// {
+// if (headerValues == null)
+// {
+// throw new ArgumentNullException("headerValues");
+// }
+
+// if (headerValues.Count > 1)
+// {
+// // Use OrderBy() instead of Array.Sort() as it performs fewer comparisons. In this case the comparisons
+// // are quite expensive so OrderBy() performs better.
+// return headerValues.OrderByDescending(m => m, MediaTypeWithQualityHeaderValueComparer.QualityComparer).ToArray();
+// }
+// else
+// {
+// return headerValues;
+// }
+// }
+
+// ///
+// /// Sort Accept-Charset, Accept-Encoding, Accept-Language and related header field values with similar syntax rules
+// /// (if more than 1) in descending order based on q-factor.
+// ///
+// /// The header values to sort.
+// /// The sorted header values.
+// protected virtual IEnumerable SortStringWithQualityHeaderValuesByQFactor(ICollection headerValues)
+// {
+// if (headerValues == null)
+// {
+// throw new ArgumentNullException("headerValues");
+// }
+
+// if (headerValues.Count > 1)
+// {
+// // Use OrderBy() instead of Array.Sort() as it performs fewer comparisons. In this case the comparisons
+// // are quite expensive so OrderBy() performs better.
+// return headerValues.OrderByDescending(m => m, StringWithQualityHeaderValueComparer.QualityComparer).ToArray();
+// }
+// else
+// {
+// return headerValues;
+// }
+// }
+
+// ///
+// /// Evaluates whether a match is better than the current match and if so returns the replacement; otherwise returns the
+// /// current match.
+// ///
+// protected virtual MediaTypeFormatterMatch UpdateBestMatch(MediaTypeFormatterMatch current, MediaTypeFormatterMatch potentialReplacement)
+// {
+// if (potentialReplacement == null)
+// {
+// return current;
+// }
+
+// if (current != null)
+// {
+// return (potentialReplacement.Quality > current.Quality) ? potentialReplacement : current;
+// }
+
+// return potentialReplacement;
+// }
+
+// private static MediaTypeFormatter[] GetWritingFormatters(IEnumerable formatters)
+// {
+// Contract.Assert(formatters != null);
+// MediaTypeFormatterCollection formatterCollection = formatters as MediaTypeFormatterCollection;
+// if (formatterCollection != null)
+// {
+// return formatterCollection.WritingFormatters;
+// }
+// return formatters.AsArray();
+// }
+
+ public ContentNegotiationResult Negotiate(Type type, IOwinContext context, IEnumerable formatters)
+ {
+ return new ContentNegotiationResult(formatters.First(), formatters.First().SupportedMediaTypes.First());
+ }
+ }
+}
diff --git a/Microsoft.AspNet.Mvc/Extensions/IEnumerableExtensions.cs b/Microsoft.AspNet.Mvc/Extensions/IEnumerableExtensions.cs
new file mode 100644
index 0000000000..fa064899e6
--- /dev/null
+++ b/Microsoft.AspNet.Mvc/Extensions/IEnumerableExtensions.cs
@@ -0,0 +1,20 @@
+using System.Diagnostics.Contracts;
+using System.Linq;
+
+namespace System.Collections.Generic
+{
+ internal static class IEnumerableExtensions
+ {
+ public static T[] AsArray(this IEnumerable values)
+ {
+ Contract.Assert(values != null);
+
+ T[] array = values as T[];
+ if (array == null)
+ {
+ array = values.ToArray();
+ }
+ return array;
+ }
+ }
+}
diff --git a/Microsoft.AspNet.Mvc/Extensions/TypeExtensions.cs b/Microsoft.AspNet.Mvc/Extensions/TypeExtensions.cs
new file mode 100644
index 0000000000..9c0845d867
--- /dev/null
+++ b/Microsoft.AspNet.Mvc/Extensions/TypeExtensions.cs
@@ -0,0 +1,91 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+using System;
+using System.Linq;
+using System.Reflection;
+
+namespace Microsoft.AspNet.Mvc
+{
+ internal static class TypeExtensions
+ {
+#if NETFX_CORE
+ private static bool EqualTo(this Type[] t1, Type[] t2)
+ {
+ if (t1.Length != t2.Length)
+ {
+ return false;
+ }
+
+ for (int idx = 0; idx < t1.Length; ++idx)
+ {
+ if (t1[idx] != t2[idx])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public static ConstructorInfo GetConstructor(this Type type, Type[] types)
+ {
+ return type.GetTypeInfo().DeclaredConstructors
+ .Where(c => c.IsPublic)
+ .SingleOrDefault(c => c.GetParameters()
+ .Select(p => p.ParameterType).ToArray().EqualTo(types));
+ }
+#endif
+
+ public static Type ExtractGenericInterface(this Type queryType, Type interfaceType)
+ {
+ Func matchesInterface = t => t.IsGenericType() && t.GetGenericTypeDefinition() == interfaceType;
+ return (matchesInterface(queryType)) ? queryType : queryType.GetInterfaces().FirstOrDefault(matchesInterface);
+ }
+
+#if NETFX_CORE
+ public static Type[] GetGenericArguments(this Type type)
+ {
+ return type.GetTypeInfo().GenericTypeArguments;
+ }
+
+ public static Type[] GetInterfaces(this Type type)
+ {
+ return type.GetTypeInfo().ImplementedInterfaces.ToArray();
+ }
+#endif
+
+#if NETFX_CORE
+ public static bool IsAssignableFrom(this Type type, Type c)
+ {
+ return type.GetTypeInfo().IsAssignableFrom(c.GetTypeInfo());
+ }
+#endif
+
+ public static bool IsGenericType(this Type type)
+ {
+#if NETFX_CORE
+ return type.GetTypeInfo().IsGenericType;
+#else
+ return type.IsGenericType;
+#endif
+ }
+
+ public static bool IsInterface(this Type type)
+ {
+#if NETFX_CORE
+ return type.GetTypeInfo().IsInterface;
+#else
+ return type.IsInterface;
+#endif
+ }
+
+ public static bool IsValueType(this Type type)
+ {
+#if NETFX_CORE
+ return type.GetTypeInfo().IsValueType;
+#else
+ return type.IsValueType;
+#endif
+ }
+ }
+}
diff --git a/Microsoft.AspNet.Mvc/Formatters/JQeryMvcForUrlEncodedFormatter.cs b/Microsoft.AspNet.Mvc/Formatters/JQeryMvcForUrlEncodedFormatter.cs
new file mode 100644
index 0000000000..96db73e393
--- /dev/null
+++ b/Microsoft.AspNet.Mvc/Formatters/JQeryMvcForUrlEncodedFormatter.cs
@@ -0,0 +1,66 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+using System;
+using System.IO;
+using System.Net.Http;
+using System.Net.Http.Formatting;
+using System.Threading.Tasks;
+
+namespace Microsoft.AspNet.Mvc
+{
+ // Supports JQuery schema on FormURL.
+ public class JQueryMvcFormUrlEncodedFormatter : FormUrlEncodedMediaTypeFormatter
+ {
+ public override bool CanReadType(Type type)
+ {
+ if (type == null)
+ {
+ throw new ArgumentNullException("type");
+ }
+
+ return true;
+ }
+
+ public override Task