ProducesAttribute +
Adding Functional Tests Conflicts: src/Microsoft.AspNet.Mvc.Core/Formatters/OutputFormatter.cs src/Microsoft.AspNet.Mvc.Core/Resources.resx src/Microsoft.AspNet.Mvc.HeaderValueAbstractions/project.json test/Microsoft.AspNet.Mvc.FunctionalTests/project.json Adding Resources + tests Conflicts: src/Microsoft.AspNet.Mvc.Core/Properties/Resources.Designer.cs src/Microsoft.AspNet.Mvc.Core/Resources.resx Adding produces content Attribute Conflicts: src/Microsoft.AspNet.Mvc.Core/Microsoft.AspNet.Mvc.Core.kproj Conflicts: src/Microsoft.AspNet.Mvc.Core/Microsoft.AspNet.Mvc.Core.kproj test/Microsoft.AspNet.Mvc.Core.Test/Microsoft.AspNet.Mvc.Core.Test.kproj
This commit is contained in:
parent
099adda3d7
commit
6ee034e64f
17
Mvc.sln
17
Mvc.sln
|
|
@ -61,6 +61,12 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Mvc.Header
|
|||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Mvc.HeaderValueAbstractions.Tests", "test\Microsoft.AspNet.Mvc.HeaderValueAbstractions.Test\Microsoft.AspNet.Mvc.HeaderValueAbstractions.Tests.kproj", "{E69FD235-2042-43A4-9970-59CB29955B4E}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{FAD65E9C-3CF3-4F68-9757-C7358604030B}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
global.json = global.json
|
||||
EndProjectSection
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ConnegWebsite", "test\WebSites\ConnegWebSite\ConnegWebsite.kproj", "{C6E5AFFA-890A-448F-8DE3-878B1D3C9FC7}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
|
@ -321,6 +327,16 @@ Global
|
|||
{E69FD235-2042-43A4-9970-59CB29955B4E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{E69FD235-2042-43A4-9970-59CB29955B4E}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{E69FD235-2042-43A4-9970-59CB29955B4E}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{C6E5AFFA-890A-448F-8DE3-878B1D3C9FC7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C6E5AFFA-890A-448F-8DE3-878B1D3C9FC7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C6E5AFFA-890A-448F-8DE3-878B1D3C9FC7}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{C6E5AFFA-890A-448F-8DE3-878B1D3C9FC7}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{C6E5AFFA-890A-448F-8DE3-878B1D3C9FC7}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{C6E5AFFA-890A-448F-8DE3-878B1D3C9FC7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C6E5AFFA-890A-448F-8DE3-878B1D3C9FC7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C6E5AFFA-890A-448F-8DE3-878B1D3C9FC7}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{C6E5AFFA-890A-448F-8DE3-878B1D3C9FC7}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{C6E5AFFA-890A-448F-8DE3-878B1D3C9FC7}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
@ -352,5 +368,6 @@ Global
|
|||
{14F79E79-AE79-48FA-95DE-D794EF4EABB3} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
|
||||
{98335B23-E4B9-4CAD-9749-0DED32A659A1} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E}
|
||||
{E69FD235-2042-43A4-9970-59CB29955B4E} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1}
|
||||
{C6E5AFFA-890A-448F-8DE3-878B1D3C9FC7} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
|||
|
|
@ -97,6 +97,12 @@ namespace MvcSample.Web
|
|||
Context.Response.WriteAsync("Hello World raw");
|
||||
}
|
||||
|
||||
[Produces("application/json", "application/custom", "text/json", Type = typeof(User))]
|
||||
public object ReturnUser()
|
||||
{
|
||||
return CreateUser();
|
||||
}
|
||||
|
||||
public User CreateUser()
|
||||
{
|
||||
User user = new User()
|
||||
|
|
|
|||
|
|
@ -71,9 +71,11 @@ namespace Microsoft.AspNet.Mvc
|
|||
|
||||
if (selectedFormatter == null)
|
||||
{
|
||||
var requestContentType = formatterContext.ActionContext.HttpContext.Request.ContentType;
|
||||
|
||||
// No formatter found based on accept headers, fall back on request contentType.
|
||||
var incomingContentType =
|
||||
MediaTypeHeaderValue.Parse(formatterContext.ActionContext.HttpContext.Request.ContentType);
|
||||
MediaTypeHeaderValue incomingContentType = null;
|
||||
MediaTypeHeaderValue.TryParse(requestContentType, out incomingContentType);
|
||||
|
||||
// In case the incomingContentType is null (as can be the case with get requests),
|
||||
// we need to pick the first formatter which
|
||||
|
|
|
|||
|
|
@ -0,0 +1,52 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNet.Mvc.Core;
|
||||
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the allowed content types and the type of the value returned by the action
|
||||
/// which can be used to select a formatter while executing <see cref="ObjectResult"/>.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
|
||||
public class ProducesAttribute : ResultFilterAttribute, IProducesMetadataProvider
|
||||
{
|
||||
public ProducesAttribute(string contentType, params string[] additionalContentTypes)
|
||||
{
|
||||
ContentTypes = GetContentTypes(contentType, additionalContentTypes);
|
||||
}
|
||||
|
||||
public Type Type { get; set; }
|
||||
|
||||
public IList<MediaTypeHeaderValue> ContentTypes { get; set; }
|
||||
|
||||
public override void OnResultExecuting([NotNull] ResultExecutingContext context)
|
||||
{
|
||||
base.OnResultExecuting(context);
|
||||
var objectResult = context.Result as ObjectResult;
|
||||
|
||||
if (objectResult != null)
|
||||
{
|
||||
objectResult.ContentTypes = ContentTypes;
|
||||
}
|
||||
}
|
||||
|
||||
private List<MediaTypeHeaderValue> GetContentTypes(string firstArg, string[] args)
|
||||
{
|
||||
var contentTypes = new List<MediaTypeHeaderValue>();
|
||||
contentTypes.Add(MediaTypeHeaderValue.Parse(firstArg));
|
||||
foreach (var item in args)
|
||||
{
|
||||
var contentType = MediaTypeHeaderValue.Parse(item);
|
||||
contentTypes.Add(contentType);
|
||||
}
|
||||
|
||||
return contentTypes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -53,8 +53,9 @@ namespace Microsoft.AspNet.Mvc
|
|||
if (encoding == null)
|
||||
{
|
||||
// Match based on request acceptHeader.
|
||||
var requestContentType = MediaTypeHeaderValue.Parse(request.ContentType);
|
||||
if (requestContentType != null && !string.IsNullOrEmpty(requestContentType.Charset))
|
||||
MediaTypeHeaderValue requestContentType = null;
|
||||
if (MediaTypeHeaderValue.TryParse(request.ContentType, out requestContentType) &&
|
||||
!string.IsNullOrEmpty(requestContentType.Charset))
|
||||
{
|
||||
var requestCharset = requestContentType.Charset;
|
||||
encoding = SupportedEncodings.FirstOrDefault(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a return type and a set of possible content types returned by a successful execution of the action.
|
||||
/// </summary>
|
||||
public interface IProducesMetadataProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Optimistic return type of the action.
|
||||
/// </summary>
|
||||
Type Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A collection of allowed content types which can be produced by the action.
|
||||
/// </summary>
|
||||
IList<MediaTypeHeaderValue> ContentTypes { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -35,28 +35,30 @@
|
|||
<Compile Include="Logging\LoggerExtensions.cs" />
|
||||
<Compile Include="Logging\MvcRouteHandlerRouteAsyncValues.cs" />
|
||||
<Compile Include="Logging\StringBuilderHelpers.cs" />
|
||||
<Compile Include="OptionDescriptors\DefaultModelBinderProvider.cs" />
|
||||
<Compile Include="OptionDescriptors\DefaultValueProviderFactoryProvider.cs" />
|
||||
<Compile Include="OptionDescriptors\DefaultViewEngineProvider.cs" />
|
||||
<Compile Include="OptionDescriptors\ModelBinderDescriptor.cs" />
|
||||
<Compile Include="OptionDescriptors\OutputFormatterDescriptorExtensions.cs" />
|
||||
<Compile Include="OptionDescriptors\ModelBinderDescriptorExtensions.cs" />
|
||||
<Compile Include="OptionDescriptors\OptionDescriptorBasedProvider.cs" />
|
||||
<Compile Include="OptionDescriptors\OptionDescriptor.cs" />
|
||||
<Compile Include="OptionDescriptors\OutputFormatterDescriptor.cs" />
|
||||
<Compile Include="OptionDescriptors\ValueProviderFactoryDescriptor.cs" />
|
||||
<Compile Include="OptionDescriptors\ViewEngineDescriptor.cs" />
|
||||
<Compile Include="OptionDescriptors\ValueProviderFactoryDescriptorExtensions.cs" />
|
||||
<Compile Include="OptionDescriptors\ViewEngineDescriptorExtensions.cs" />
|
||||
<Compile Include="Filters\ProducesAttribute.cs" />
|
||||
<Compile Include="Formatters\DefaultOutputFormattersProvider.cs" />
|
||||
<Compile Include="Formatters\IOutputFormatter.cs" />
|
||||
<Compile Include="Formatters\StringWithQualityHeaderValueComparer.cs" />
|
||||
<Compile Include="IProducesMetadataProvider.cs" />
|
||||
<Compile Include="Formatters\IOutputFormattersProvider.cs" />
|
||||
<Compile Include="Formatters\OutputFormatterContext.cs" />
|
||||
<Compile Include="Formatters\HeaderParsingHelpers.cs" />
|
||||
<Compile Include="Formatters\JsonOutputFormatter.cs" />
|
||||
<Compile Include="Formatters\MediaTypeWithQualityHeaderValueComparer.cs" />
|
||||
<Compile Include="Formatters\OutputFormatter.cs" />
|
||||
<Compile Include="OptionDescriptors\DefaultModelBinderProvider.cs" />
|
||||
<Compile Include="OptionDescriptors\DefaultValueProviderFactoryProvider.cs" />
|
||||
<Compile Include="OptionDescriptors\DefaultViewEngineProvider.cs" />
|
||||
<Compile Include="OptionDescriptors\ModelBinderDescriptor.cs" />
|
||||
<Compile Include="OptionDescriptors\ModelBinderDescriptorExtensions.cs" />
|
||||
<Compile Include="OptionDescriptors\OptionDescriptor.cs" />
|
||||
<Compile Include="OptionDescriptors\OptionDescriptorBasedProvider.cs" />
|
||||
<Compile Include="OptionDescriptors\OutputFormatterDescriptor.cs" />
|
||||
<Compile Include="OptionDescriptors\OutputFormatterDescriptorExtensions.cs" />
|
||||
<Compile Include="OptionDescriptors\ValueProviderFactoryDescriptor.cs" />
|
||||
<Compile Include="OptionDescriptors\ValueProviderFactoryDescriptorExtensions.cs" />
|
||||
<Compile Include="OptionDescriptors\ViewEngineDescriptor.cs" />
|
||||
<Compile Include="OptionDescriptors\ViewEngineDescriptorExtensions.cs" />
|
||||
<Compile Include="ParameterBinding\ModelBindingHelper.cs" />
|
||||
<Compile Include="ActionInvokerFactory.cs" />
|
||||
<Compile Include="ActionInvokerProviderContext.cs" />
|
||||
|
|
|
|||
|
|
@ -52,16 +52,28 @@ namespace Microsoft.AspNet.Mvc.HeaderValueAbstractions
|
|||
|
||||
public static MediaTypeHeaderValue Parse(string input)
|
||||
{
|
||||
MediaTypeHeaderValue headerValue = null;
|
||||
if (!TryParse(input, out headerValue))
|
||||
{
|
||||
throw new ArgumentException(Resources.FormatInvalidContentType(input));
|
||||
}
|
||||
|
||||
return headerValue;
|
||||
}
|
||||
|
||||
public static bool TryParse(string input, out MediaTypeHeaderValue headerValue)
|
||||
{
|
||||
headerValue = null;
|
||||
if (string.IsNullOrEmpty(input))
|
||||
{
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
|
||||
var inputArray = input.Split(new[] { ';' }, 2);
|
||||
var mediaTypeParts = inputArray[0].Split('/');
|
||||
if (mediaTypeParts.Length != 2)
|
||||
{
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: throw if the media type and subtypes are invalid.
|
||||
|
|
@ -85,7 +97,7 @@ namespace Microsoft.AspNet.Mvc.HeaderValueAbstractions
|
|||
parameters.TryGetValue("charset", out charset);
|
||||
}
|
||||
|
||||
var mediaTypeHeader = new MediaTypeHeaderValue()
|
||||
headerValue = new MediaTypeHeaderValue()
|
||||
{
|
||||
MediaType = mediaType,
|
||||
MediaSubType = mediaSubType,
|
||||
|
|
@ -94,7 +106,7 @@ namespace Microsoft.AspNet.Mvc.HeaderValueAbstractions
|
|||
Parameters = parameters ?? new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase),
|
||||
};
|
||||
|
||||
return mediaTypeHeader;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected static Dictionary<string, string> ParseParameters(string inputString)
|
||||
|
|
|
|||
|
|
@ -21,10 +21,16 @@
|
|||
<Compile Include="MediaTypeHeaderValue.cs" />
|
||||
<Compile Include="MediaTypeHeaderValueRange.cs" />
|
||||
<Compile Include="MediaTypeWithQualityHeaderValue.cs" />
|
||||
<Compile Include="Properties\Resources.Designer.cs" />
|
||||
<Compile Include="StringWithQualityHeaderValue.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="project.json" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
46
src/Microsoft.AspNet.Mvc.HeaderValueAbstractions/Properties/Resources.Designer.cs
generated
Normal file
46
src/Microsoft.AspNet.Mvc.HeaderValueAbstractions/Properties/Resources.Designer.cs
generated
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
// <auto-generated />
|
||||
namespace Microsoft.AspNet.Mvc.HeaderValueAbstractions
|
||||
{
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
|
||||
internal static class Resources
|
||||
{
|
||||
private static readonly ResourceManager _resourceManager
|
||||
= new ResourceManager("Microsoft.AspNet.Mvc.HeaderValueAbstractions.Resources", typeof(Resources).GetTypeInfo().Assembly);
|
||||
|
||||
/// <summary>
|
||||
/// Invalid Argument. Content type '{0}' could not be parsed.
|
||||
/// </summary>
|
||||
internal static string InvalidContentType
|
||||
{
|
||||
get { return GetString("InvalidContentType"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invalid Argument. Content type '{0}' could not be parsed.
|
||||
/// </summary>
|
||||
internal static string FormatInvalidContentType(object p0)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("InvalidContentType"), p0);
|
||||
}
|
||||
|
||||
private static string GetString(string name, params string[] formatterNames)
|
||||
{
|
||||
var value = _resourceManager.GetString(name);
|
||||
|
||||
System.Diagnostics.Debug.Assert(value != null);
|
||||
|
||||
if (formatterNames != null)
|
||||
{
|
||||
for (var i = 0; i < formatterNames.Length; i++)
|
||||
{
|
||||
value = value.Replace("{" + formatterNames[i] + "}", "{" + i + "}");
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="InvalidContentType" xml:space="preserve">
|
||||
<value>Invalid Argument. Content type '{0}' could not be parsed.</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -6,6 +6,8 @@
|
|||
"k10": {
|
||||
"dependencies": {
|
||||
"System.Collections": "4.0.10.0",
|
||||
"System.Diagnostics.Debug": "4.0.10.0",
|
||||
"System.Resources.ResourceManager": "4.0.0.0",
|
||||
"System.Runtime": "4.0.20.0",
|
||||
"System.Runtime.Extensions": "4.0.10.0"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,80 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
|
||||
using Microsoft.AspNet.PipelineCore;
|
||||
using Microsoft.AspNet.Routing;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Test
|
||||
{
|
||||
public class ProducesAttributeTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task ProducesContentAttribute_SetsContentType()
|
||||
{
|
||||
// Arrange
|
||||
var mediaType1 = MediaTypeHeaderValue.Parse("application/json");
|
||||
var mediaType2 = MediaTypeHeaderValue.Parse("text/json;charset=utf-8");
|
||||
var producesContentAttribute = new ProducesAttribute("application/json", "text/json;charset=utf-8");
|
||||
var resultExecutingContext = CreateResultExecutingContext(producesContentAttribute);
|
||||
var next = new ResultExecutionDelegate(
|
||||
() => Task.FromResult(CreateResultExecutedContext(resultExecutingContext)));
|
||||
|
||||
// Act
|
||||
await producesContentAttribute.OnResultExecutionAsync(resultExecutingContext, next);
|
||||
|
||||
// Assert
|
||||
var objectResult = resultExecutingContext.Result as ObjectResult;
|
||||
Assert.Equal(2, objectResult.ContentTypes.Count);
|
||||
ValidateMediaType(mediaType1, objectResult.ContentTypes[0]);
|
||||
ValidateMediaType(mediaType2, objectResult.ContentTypes[1]);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("")]
|
||||
[InlineData(null)]
|
||||
[InlineData("invalid")]
|
||||
public void ProducesAttribute_InvalidContentType_Throws(string content)
|
||||
{
|
||||
// Act & Assert
|
||||
var ex = Assert.Throws<ArgumentException>(
|
||||
() => new ProducesAttribute(content));
|
||||
Assert.Equal("Invalid Argument. Content type '" + content + "' could not be parsed.",
|
||||
ex.Message);
|
||||
}
|
||||
|
||||
private static void ValidateMediaType(MediaTypeHeaderValue expectedMediaType, MediaTypeHeaderValue actualMediaType)
|
||||
{
|
||||
Assert.Equal(expectedMediaType.MediaType, actualMediaType.MediaType);
|
||||
Assert.Equal(expectedMediaType.MediaSubType, actualMediaType.MediaSubType);
|
||||
Assert.Equal(expectedMediaType.Charset, actualMediaType.Charset);
|
||||
Assert.Equal(expectedMediaType.MediaTypeRange, actualMediaType.MediaTypeRange);
|
||||
Assert.Equal(expectedMediaType.Parameters.Count, actualMediaType.Parameters.Count);
|
||||
foreach (var item in expectedMediaType.Parameters)
|
||||
{
|
||||
Assert.Equal(item.Value, actualMediaType.Parameters[item.Key]);
|
||||
}
|
||||
}
|
||||
|
||||
private static ResultExecutedContext CreateResultExecutedContext(ResultExecutingContext context)
|
||||
{
|
||||
return new ResultExecutedContext(context, context.Filters, context.Result);
|
||||
}
|
||||
|
||||
private static ResultExecutingContext CreateResultExecutingContext(IFilter filter)
|
||||
{
|
||||
return new ResultExecutingContext(
|
||||
CreateActionContext(),
|
||||
new IFilter[] { filter, },
|
||||
new ObjectResult("Some Value"));
|
||||
}
|
||||
|
||||
private static ActionContext CreateActionContext()
|
||||
{
|
||||
return new ActionContext(new DefaultHttpContext(), new RouteData(), new ActionDescriptor());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -31,6 +31,8 @@
|
|||
<Compile Include="ActionResults\RedirectToActionResultTest.cs" />
|
||||
<Compile Include="ActionResults\RedirectToRouteResultTest.cs" />
|
||||
<Compile Include="AntiXsrf\AntiForgeryOptionsTests.cs" />
|
||||
<Compile Include="Filters\ProducesAttributeTests.cs" />
|
||||
<Compile Include="Formatters\OutputFormatterTests.cs" />
|
||||
<Compile Include="Formatters\TextPlainFormatterTests.cs" />
|
||||
<Compile Include="Logging\BeginScopeContext.cs" />
|
||||
<Compile Include="Logging\TestLoggerFactory.cs" />
|
||||
|
|
@ -40,6 +42,7 @@
|
|||
<Compile Include="Logging\NullLoggerFactory.cs" />
|
||||
<Compile Include="Logging\TestSink.cs" />
|
||||
<Compile Include="Logging\TestLogger.cs" />
|
||||
<Compile Include="MediaTypeWithQualityHeaderValueTests.cs" />
|
||||
<Compile Include="MvcRouteHandlerTests.cs" />
|
||||
<Compile Include="OptionDescriptors\DefaultModelBindersProviderTest.cs" />
|
||||
<Compile Include="OptionDescriptors\DefaultValueProviderFactoryProviderTest.cs" />
|
||||
|
|
@ -48,12 +51,10 @@
|
|||
<Compile Include="OptionDescriptors\ModelBinderDescriptorTest.cs" />
|
||||
<Compile Include="OptionDescriptors\OutputFormatterDescriptorExtensionTest.cs" />
|
||||
<Compile Include="OptionDescriptors\OutputFormatterDescriptorTest.cs" />
|
||||
<Compile Include="OptionDescriptors\ValueProviderFactoryDescriptorExtensionsTest.cs" />
|
||||
<Compile Include="OptionDescriptors\ValueProviderFactoryDescriptorTest.cs" />
|
||||
<Compile Include="OptionDescriptors\ViewEngineDescriptorTest.cs" />
|
||||
<Compile Include="OptionDescriptors\ValueProviderFactoryDescriptorExtensionsTest.cs" />
|
||||
<Compile Include="OptionDescriptors\ViewEngineDscriptorExtensionsTest.cs" />
|
||||
<Compile Include="Formatters\OutputFormatterTests.cs" />
|
||||
<Compile Include="MediaTypeWithQualityHeaderValueTests.cs" />
|
||||
<Compile Include="ParameterBinding\ModelBindingHelperTest.cs" />
|
||||
<Compile Include="AntiXsrf\AntiForgeryTokenSerializerTest.cs" />
|
||||
<Compile Include="AntiXsrf\ITokenProvider.cs" />
|
||||
|
|
@ -92,8 +93,8 @@
|
|||
<Compile Include="Rendering\DefaultDisplayTemplatesTests.cs" />
|
||||
<Compile Include="Rendering\DefaultEditorTemplatesTests.cs" />
|
||||
<Compile Include="Rendering\DefaultTemplatesUtilities.cs" />
|
||||
<Compile Include="Rendering\HtmlHelperDisplayNameExtensionsTest.cs" />
|
||||
<Compile Include="Rendering\HtmlAttributePropertyHelperTest.cs" />
|
||||
<Compile Include="Rendering\HtmlHelperDisplayNameExtensionsTest.cs" />
|
||||
<Compile Include="Rendering\HtmlHelperDisplayTextTest.cs" />
|
||||
<Compile Include="Rendering\HtmlHelperLabelExtensionsTest.cs" />
|
||||
<Compile Include="Rendering\HtmlHelperNameExtensionsTest.cs" />
|
||||
|
|
@ -103,10 +104,10 @@
|
|||
<Compile Include="KnownRouteValueConstraintTests.cs" />
|
||||
<Compile Include="Routing\AttributeRoutePrecedenceTests.cs" />
|
||||
<Compile Include="Routing\AttributeRouteTemplateTests.cs" />
|
||||
<Compile Include="Routing\AttributeRouteTests.cs" />
|
||||
<Compile Include="Routing\AttributeRoutingTest.cs" />
|
||||
<Compile Include="StaticActionDiscoveryConventions.cs" />
|
||||
<Compile Include="StaticControllerAssemblyProvider.cs" />
|
||||
<Compile Include="Routing\AttributeRouteTests.cs" />
|
||||
<Compile Include="TestController.cs" />
|
||||
<Compile Include="TypeHelperTest.cs" />
|
||||
<Compile Include="UrlHelperTest.cs" />
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"Microsoft.AspNet.Http": "1.0.0-*",
|
||||
"Microsoft.AspNet.PipelineCore": "1.0.0-*",
|
||||
"Microsoft.AspNet.Mvc.HeaderValueAbstractions": "1.0.0-*",
|
||||
"Microsoft.AspNet.Mvc" : "",
|
||||
"Microsoft.AspNet.Mvc.Core" : "",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,253 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using ConnegWebsite;
|
||||
using Microsoft.AspNet.Builder;
|
||||
using Microsoft.AspNet.TestHost;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.FunctionalTests
|
||||
{
|
||||
public class ConnegTests
|
||||
{
|
||||
private readonly IServiceProvider _provider = TestHelper.CreateServices("ConnegWebsite");
|
||||
private readonly Action<IBuilder> _app = new Startup().Configure;
|
||||
|
||||
[Fact]
|
||||
public async Task ProducesContentAttribute_SingleContentType_PicksTheFirstSupportedFormatter()
|
||||
{
|
||||
// Arrange
|
||||
var server = TestServer.Create(_provider, _app);
|
||||
var client = server.Handler;
|
||||
|
||||
// Selects custom even though it is last in the list.
|
||||
var expectedContentType = "application/custom;charset=utf-8";
|
||||
var expectedBody = "Written using custom format.";
|
||||
|
||||
// Act
|
||||
var result = await client.GetAsync("http://localhost/Normal/WriteUserUsingCustomFormat");
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expectedContentType, result.HttpContext.Response.ContentType);
|
||||
var body = await result.HttpContext.Response.ReadBodyAsStringAsync();
|
||||
Assert.Equal(expectedBody, body);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ProducesContentAttribute_MultipleContentTypes_RunsConnegToSelectFormatter()
|
||||
{
|
||||
// Arrange
|
||||
var server = TestServer.Create(_provider, _app);
|
||||
var client = server.Handler;
|
||||
var expectedContentType = "application/json;charset=utf-8";
|
||||
var expectedBody = "{\r\n \"Name\": \"My name\",\r\n \"Address\": \"My address\"\r\n}";
|
||||
|
||||
// Act
|
||||
var result = await client.GetAsync("http://localhost/Normal/MultipleAllowedContentTypes");
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expectedContentType, result.HttpContext.Response.ContentType);
|
||||
var body = await result.HttpContext.Response.ReadBodyAsStringAsync();
|
||||
Assert.Equal(expectedBody, body);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task NoProducesContentAttribute_ActionReturningString_RunsUsingTextFormatter()
|
||||
{
|
||||
// Arrange
|
||||
var server = TestServer.Create(_provider, _app);
|
||||
var client = server.Handler;
|
||||
var expectedContentType = "text/plain;charset=utf-8";
|
||||
var expectedBody = "NormalController";
|
||||
|
||||
// Act
|
||||
var result = await client.GetAsync("http://localhost/Normal/ReturnClassName");
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expectedContentType, result.HttpContext.Response.ContentType);
|
||||
var body = await result.HttpContext.Response.ReadBodyAsStringAsync();
|
||||
Assert.Equal(expectedBody, body);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task NoProducesContentAttribute_ActionReturningAnyObject_RunsUsingDefaultFormatters()
|
||||
{
|
||||
// Arrange
|
||||
var server = TestServer.Create(_provider, _app);
|
||||
var client = server.Handler;
|
||||
var expectedContentType = "application/json;charset=utf-8";
|
||||
//var expectedBody = "\"NormalController\"";
|
||||
|
||||
// Act
|
||||
var result = await client.GetAsync("http://localhost/Normal/ReturnUser");
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expectedContentType, result.HttpContext.Response.ContentType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task NoMatchingFormatter_ForTheGivenContentType_Returns406()
|
||||
{
|
||||
// Arrange
|
||||
var server = TestServer.Create(_provider, _app);
|
||||
var client = server.Handler;
|
||||
|
||||
// Act
|
||||
var result = await client.GetAsync("http://localhost/Normal/ReturnUser_NoMatchingFormatter");
|
||||
|
||||
// Assert
|
||||
Assert.Equal(406, result.HttpContext.Response.StatusCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ProducesContentAttribute_OnAction_OverridesTheValueOnClass()
|
||||
{
|
||||
var server = TestServer.Create(_provider, _app);
|
||||
var client = server.Handler;
|
||||
|
||||
// Value on the class is application/json.
|
||||
var expectedContentType = "application/custom_ProducesContentBaseController_Action;charset=utf-8";
|
||||
var expectedBody = "ProducesContentBaseController";
|
||||
|
||||
// Act
|
||||
var result = await client.GetAsync("http://localhost/ProducesContentBase/ReturnClassName");
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expectedContentType, result.HttpContext.Response.ContentType);
|
||||
var body = await result.HttpContext.Response.ReadBodyAsStringAsync();
|
||||
Assert.Equal(expectedBody, body);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ProducesContentAttribute_OnDerivedClass_OverridesTheValueOnBaseClass()
|
||||
{
|
||||
var server = TestServer.Create(_provider, _app);
|
||||
var client = server.Handler;
|
||||
var expectedContentType = "application/custom_ProducesContentOnClassController;charset=utf-8";
|
||||
var expectedBody = "ProducesContentOnClassController";
|
||||
|
||||
// Act
|
||||
var result = await client.GetAsync(
|
||||
"http://localhost/ProducesContentOnClass/ReturnClassNameWithNoContentTypeOnAction");
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expectedContentType, result.HttpContext.Response.ContentType);
|
||||
var body = await result.HttpContext.Response.ReadBodyAsStringAsync();
|
||||
Assert.Equal(expectedBody, body);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ProducesContentAttribute_OnDerivedAction_OverridesTheValueOnBaseClass()
|
||||
{
|
||||
var server = TestServer.Create(_provider, _app);
|
||||
var client = server.Handler;
|
||||
var expectedContentType = "application/custom_NoProducesContentOnClassController_Action;charset=utf-8";
|
||||
var expectedBody = "NoProducesContentOnClassController";
|
||||
|
||||
// Act
|
||||
var result = await client.GetAsync("http://localhost/NoProducesContentOnClass/ReturnClassName");
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expectedContentType, result.HttpContext.Response.ContentType);
|
||||
var body = await result.HttpContext.Response.ReadBodyAsStringAsync();
|
||||
Assert.Equal(expectedBody, body);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ProducesContentAttribute_OnDerivedAction_OverridesTheValueOnBaseAction()
|
||||
{
|
||||
var server = TestServer.Create(_provider, _app);
|
||||
var client = server.Handler;
|
||||
var expectedContentType = "application/custom_NoProducesContentOnClassController_Action;charset=utf-8";
|
||||
var expectedBody = "NoProducesContentOnClassController";
|
||||
|
||||
// Act
|
||||
var result = await client.GetAsync("http://localhost/NoProducesContentOnClass/ReturnClassName");
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expectedContentType, result.HttpContext.Response.ContentType);
|
||||
var body = await result.HttpContext.Response.ReadBodyAsStringAsync();
|
||||
Assert.Equal(expectedBody, body);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ProducesContentAttribute_OnDerivedClassAndAction_OverridesTheValueOnBaseClass()
|
||||
{
|
||||
// Arrange
|
||||
var server = TestServer.Create(_provider, _app);
|
||||
var client = server.Handler;
|
||||
var expectedContentType = "application/custom_ProducesContentOnClassController_Action;charset=utf-8";
|
||||
var expectedBody = "ProducesContentOnClassController";
|
||||
|
||||
// Act
|
||||
var result = await client.GetAsync("http://localhost/ProducesContentOnClass/ReturnClassNameContentTypeOnDerivedAction");
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expectedContentType, result.HttpContext.Response.ContentType);
|
||||
var body = await result.HttpContext.Response.ReadBodyAsStringAsync();
|
||||
Assert.Equal(expectedBody, body);
|
||||
}
|
||||
|
||||
|
||||
[InlineData("ReturnTaskOfString")]
|
||||
[InlineData("ReturnTaskOfObject_StringValue")]
|
||||
[InlineData("ReturnString")]
|
||||
[InlineData("ReturnObject_StringValue")]
|
||||
[InlineData("ReturnString_NullValue")]
|
||||
public async Task TextPlainFormatter_ReturnsTextPlainContentType(string actionName)
|
||||
{
|
||||
// Arrange
|
||||
var server = TestServer.Create(_provider, _app);
|
||||
var client = server.Handler;
|
||||
var expectedContentType = "text/plain;charset=utf-8";
|
||||
var expectedBody = actionName;
|
||||
|
||||
// Act
|
||||
var result = await client.GetAsync("http://localhost/TextPlain/" + actionName);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expectedContentType, result.HttpContext.Response.ContentType);
|
||||
var body = await result.HttpContext.Response.ReadBodyAsStringAsync();
|
||||
Assert.Equal(expectedBody, body);
|
||||
}
|
||||
|
||||
[InlineData("ReturnTaskOfObject_ObjectValue")]
|
||||
[InlineData("ReturnObject_ObjectValue")]
|
||||
[InlineData("ReturnObject_NullValue")]
|
||||
public async Task TextPlainFormatter_DoesNotSelectTextPlainFormatterForNonStringValue(string actionName)
|
||||
{
|
||||
// Arrange
|
||||
var server = TestServer.Create(_provider, _app);
|
||||
var client = server.Handler;
|
||||
var expectedContentType = "application/json;charset=utf-8";
|
||||
var expectedBody = actionName;
|
||||
|
||||
// Act
|
||||
var result = await client.GetAsync("http://localhost/TextPlain/" + actionName);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expectedContentType, result.HttpContext.Response.ContentType);
|
||||
var body = await result.HttpContext.Response.ReadBodyAsStringAsync();
|
||||
}
|
||||
|
||||
[InlineData("ReturnString_NullValue")]
|
||||
public async Task TextPlainFormatter_DoesNotWriteNullValue(string actionName)
|
||||
{
|
||||
// Arrange
|
||||
var server = TestServer.Create(_provider, _app);
|
||||
var client = server.Handler;
|
||||
var expectedContentType = "text/plain;charset=utf-8";
|
||||
string expectedBody = null;
|
||||
|
||||
// Act
|
||||
var result = await client.GetAsync("http://localhost/TextPlain/" + actionName);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expectedContentType, result.HttpContext.Response.ContentType);
|
||||
var body = await result.HttpContext.Response.ReadBodyAsStringAsync();
|
||||
Assert.Equal(expectedBody, body);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -31,6 +31,7 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="BasicTests.cs" />
|
||||
<Compile Include="ConnegTests.cs" />
|
||||
<Compile Include="ViewEngineTests.cs" />
|
||||
<Compile Include="ActivatorTests.cs" />
|
||||
<Compile Include="ValueProviderTests.cs" />
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
"ActivatorWebSite": "",
|
||||
"BasicWebSite": "",
|
||||
"CompositeViewEngine": "",
|
||||
"ConnegWebsite": "",
|
||||
"FormatterWebSite": "",
|
||||
"InlineConstraintsWebSite": "",
|
||||
"Microsoft.AspNet.TestHost": "1.0.0-*",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="__ToolsVersion__" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">12.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>c6e5affa-890a-448f-8de3-878b1d3c9fc7</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="$(OutputType) == 'Console'">
|
||||
<DebuggerFlavor>ConsoleDebugger</DebuggerFlavor>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="$(OutputType) == 'Web'">
|
||||
<DebuggerFlavor>WebDebugger</DebuggerFlavor>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x86'" Label="Configuration">
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'" Label="Configuration">
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Project.json" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Controllers\NormalController.cs" />
|
||||
<Compile Include="Controllers\NoProducesContentOnClassController.cs" />
|
||||
<Compile Include="Controllers\ProducesContentBaseController.cs" />
|
||||
<Compile Include="Controllers\ProducesContentOnClassController.cs" />
|
||||
<Compile Include="Controllers\HomeController.cs" />
|
||||
<Compile Include="Controllers\TextPlainController.cs" />
|
||||
<Compile Include="Models\User.cs" />
|
||||
<Compile Include="ContentType.cs" />
|
||||
<Compile Include="PlainTextFormatter.cs" />
|
||||
<Compile Include="Startup.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Mvc;
|
||||
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
|
||||
|
||||
namespace ConnegWebsite
|
||||
{
|
||||
public class CustomFormatter : OutputFormatter
|
||||
{
|
||||
public string ContentType { get; private set; }
|
||||
|
||||
public CustomFormatter(string contentType)
|
||||
{
|
||||
ContentType = contentType;
|
||||
SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse(contentType));
|
||||
SupportedEncodings.Add(Encoding.GetEncoding("utf-8"));
|
||||
}
|
||||
|
||||
public override bool CanWriteResult(OutputFormatterContext context, MediaTypeHeaderValue contentType)
|
||||
{
|
||||
if (base.CanWriteResult(context, contentType))
|
||||
{
|
||||
var actionReturnString = context.Object as string;
|
||||
if (actionReturnString != null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override async Task WriteResponseBodyAsync(OutputFormatterContext context)
|
||||
{
|
||||
var response = context.ActionContext.HttpContext.Response;
|
||||
response.ContentType = ContentType + ";charset=utf-8";
|
||||
await response.WriteAsync(context.Object as string);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Mvc;
|
||||
|
||||
namespace ConnegWebsite
|
||||
{
|
||||
public class HomeController : Controller
|
||||
{
|
||||
public IActionResult Index()
|
||||
{
|
||||
return new JsonResult("Index Method");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Mvc;
|
||||
|
||||
namespace ConnegWebsite
|
||||
{
|
||||
public class NoProducesContentOnClassController : ProducesContentBaseController
|
||||
{
|
||||
public override void OnActionExecuted(ActionExecutedContext context)
|
||||
{
|
||||
var result = context.Result as ObjectResult;
|
||||
if (result != null)
|
||||
{
|
||||
result.Formatters.Add(new CustomFormatter("application/custom_NoProducesContentOnClassController_Action"));
|
||||
}
|
||||
|
||||
base.OnActionExecuted(context);
|
||||
}
|
||||
|
||||
[Produces("application/custom_NoProducesContentOnClassController_Action")]
|
||||
public override string ReturnClassName()
|
||||
{
|
||||
// should be written using the formatter provided by this action and not the base action.
|
||||
return "NoProducesContentOnClassController";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Mvc;
|
||||
|
||||
namespace ConnegWebsite
|
||||
{
|
||||
public class NormalController : Controller
|
||||
{
|
||||
public override void OnActionExecuted(ActionExecutedContext context)
|
||||
{
|
||||
var result = context.Result as ObjectResult;
|
||||
if (result != null)
|
||||
{
|
||||
result.Formatters.Add(new PlainTextFormatter());
|
||||
result.Formatters.Add(new CustomFormatter("application/custom"));
|
||||
result.Formatters.Add(new JsonOutputFormatter(JsonOutputFormatter.CreateDefaultSettings(),
|
||||
indent: true));
|
||||
}
|
||||
|
||||
base.OnActionExecuted(context);
|
||||
}
|
||||
|
||||
public string ReturnClassName()
|
||||
{
|
||||
return "NormalController";
|
||||
}
|
||||
|
||||
public User ReturnUser()
|
||||
{
|
||||
return CreateUser();
|
||||
}
|
||||
|
||||
[Produces("application/NoFormatter")]
|
||||
public User ReturnUser_NoMatchingFormatter()
|
||||
{
|
||||
return CreateUser();
|
||||
}
|
||||
|
||||
[Produces("application/custom", "application/json", "text/json")]
|
||||
public User MultipleAllowedContentTypes()
|
||||
{
|
||||
return CreateUser();
|
||||
}
|
||||
|
||||
[Produces("application/custom")]
|
||||
public string WriteUserUsingCustomFormat()
|
||||
{
|
||||
return "Written using custom format.";
|
||||
}
|
||||
|
||||
[NonAction]
|
||||
public User CreateUser()
|
||||
{
|
||||
User user = new User()
|
||||
{
|
||||
Name = "My name",
|
||||
Address = "My address",
|
||||
};
|
||||
|
||||
return user;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Mvc;
|
||||
|
||||
namespace ConnegWebsite
|
||||
{
|
||||
[Produces("application/custom_ProducesContentBaseController")]
|
||||
public class ProducesContentBaseController : Controller
|
||||
{
|
||||
public override void OnActionExecuted(ActionExecutedContext context)
|
||||
{
|
||||
var result = context.Result as ObjectResult;
|
||||
if(result != null)
|
||||
{
|
||||
result.Formatters.Add(new PlainTextFormatter());
|
||||
result.Formatters.Add(new CustomFormatter("application/custom_ProducesContentBaseController"));
|
||||
result.Formatters.Add(new CustomFormatter("application/custom_ProducesContentBaseController_Action"));
|
||||
}
|
||||
|
||||
base.OnActionExecuted(context);
|
||||
}
|
||||
|
||||
[Produces("application/custom_ProducesContentBaseController_Action")]
|
||||
public virtual string ReturnClassName()
|
||||
{
|
||||
// Should be written using the action's content type. Overriding the one at the class.
|
||||
return "ProducesContentBaseController";
|
||||
}
|
||||
|
||||
public virtual string ReturnClassNameWithNoContentTypeOnAction()
|
||||
{
|
||||
// Should be written using the action's content type. Overriding the one at the class.
|
||||
return "ProducesContentBaseController";
|
||||
}
|
||||
|
||||
public virtual string ReturnClassNameContentTypeOnDerivedAction()
|
||||
{
|
||||
return "ProducesContentBaseController";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Mvc;
|
||||
|
||||
namespace ConnegWebsite
|
||||
{
|
||||
[Produces("application/custom_ProducesContentOnClassController")]
|
||||
public class ProducesContentOnClassController : ProducesContentBaseController
|
||||
{
|
||||
public override void OnActionExecuted(ActionExecutedContext context)
|
||||
{
|
||||
var result = context.Result as ObjectResult;
|
||||
if (result != null)
|
||||
{
|
||||
result.Formatters.Add(new CustomFormatter("application/custom_ProducesContentOnClassController"));
|
||||
result.Formatters.Add(
|
||||
new CustomFormatter("application/custom_ProducesContentOnClassController_Action"));
|
||||
}
|
||||
|
||||
base.OnActionExecuted(context);
|
||||
}
|
||||
|
||||
// No Content type defined by the derived class action.
|
||||
public override string ReturnClassName()
|
||||
{
|
||||
// should be written using the content defined at base class's action.
|
||||
return "ProducesContentOnClassController";
|
||||
}
|
||||
|
||||
public override string ReturnClassNameWithNoContentTypeOnAction()
|
||||
{
|
||||
// should be written using the content defined at derived class's class.
|
||||
return "ProducesContentOnClassController";
|
||||
}
|
||||
|
||||
[Produces("application/custom_ProducesContentOnClassController_Action")]
|
||||
public override string ReturnClassNameContentTypeOnDerivedAction()
|
||||
{
|
||||
// should be written using the content defined at derived class's class.
|
||||
return "ProducesContentOnClassController";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Mvc;
|
||||
|
||||
namespace ConnegWebsite
|
||||
{
|
||||
public class TextPlainController : Controller
|
||||
{
|
||||
public Task<string> ReturnTaskOfString()
|
||||
{
|
||||
return Task.FromResult<string>("ReturnTaskOfString");
|
||||
}
|
||||
|
||||
public Task<object> ReturnTaskOfObject_StringValue()
|
||||
{
|
||||
return Task.FromResult<object>("ReturnTaskOfObject_StringValue");
|
||||
}
|
||||
|
||||
public Task<object> ReturnTaskOfObject_ObjectValue()
|
||||
{
|
||||
return Task.FromResult<object>(new object());
|
||||
}
|
||||
|
||||
public string ReturnString()
|
||||
{
|
||||
return "ReturnString";
|
||||
}
|
||||
|
||||
public object ReturnObject_StringValue()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
public object ReturnObject_ObjectValue()
|
||||
{
|
||||
return new object();
|
||||
}
|
||||
|
||||
public string ReturnString_NullValue()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public object ReturnObject_NullValue()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace ConnegWebsite
|
||||
{
|
||||
[DisplayColumn("Name")]
|
||||
public class User
|
||||
{
|
||||
[Required]
|
||||
[MinLength(4)]
|
||||
public string Name { get; set; }
|
||||
public string Address { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Mvc;
|
||||
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
|
||||
|
||||
namespace ConnegWebsite
|
||||
{
|
||||
public class PlainTextFormatter : OutputFormatter
|
||||
{
|
||||
public PlainTextFormatter()
|
||||
{
|
||||
SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("text/plain"));
|
||||
SupportedEncodings.Add(Encoding.GetEncoding("utf-8"));
|
||||
}
|
||||
|
||||
public override bool CanWriteResult(OutputFormatterContext context, MediaTypeHeaderValue contentType)
|
||||
{
|
||||
if (base.CanWriteResult(context, contentType))
|
||||
{
|
||||
var actionReturnString = context.Object as string;
|
||||
if (actionReturnString != null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override async Task WriteResponseBodyAsync(OutputFormatterContext context)
|
||||
{
|
||||
var response = context.ActionContext.HttpContext.Response;
|
||||
response.ContentType = "text/plain;charset=utf-8";
|
||||
await response.WriteAsync(context.Object as string);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Builder;
|
||||
using Microsoft.AspNet.Routing;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
|
||||
namespace ConnegWebsite
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
public void Configure(IBuilder app)
|
||||
{
|
||||
var configuration = app.GetTestConfiguration();
|
||||
|
||||
// Set up application services
|
||||
app.UseServices(services =>
|
||||
{
|
||||
// Add MVC services to the services container
|
||||
services.AddMvc(configuration);
|
||||
});
|
||||
|
||||
// Add MVC to the request pipeline
|
||||
app.UseMvc(routes =>
|
||||
{
|
||||
routes.MapRoute("ActionAsMethod", "{controller}/{action}",
|
||||
defaults: new { controller = "Home", action = "Index" });
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"Microsoft.AspNet.Mvc": "",
|
||||
"Microsoft.AspNet.Server.IIS": "1.0.0-*",
|
||||
"Microsoft.AspNet.Mvc.TestConfiguration": ""
|
||||
},
|
||||
"frameworks": {
|
||||
"net45": { },
|
||||
"k10": { }
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue