Consume new strongly typed headers. Remove temp implementations.

This commit is contained in:
Chris Ross 2015-01-14 15:51:34 -08:00
parent 8529ea2f0d
commit 91d7e382d1
78 changed files with 299 additions and 1807 deletions

View File

@ -33,10 +33,6 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Mvc.Razor.
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Mvc.Test", "test\Microsoft.AspNet.Mvc.Test\Microsoft.AspNet.Mvc.Test.kproj", "{5F945B82-FE5F-425C-956C-8BC2F2020254}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Mvc.HeaderValueAbstractions", "src\Microsoft.AspNet.Mvc.HeaderValueAbstractions\Microsoft.AspNet.Mvc.HeaderValueAbstractions.kproj", "{98335B23-E4B9-4CAD-9749-0DED32A659A1}"
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
@ -178,26 +174,6 @@ Global
{5F945B82-FE5F-425C-956C-8BC2F2020254}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{5F945B82-FE5F-425C-956C-8BC2F2020254}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{5F945B82-FE5F-425C-956C-8BC2F2020254}.Release|x86.ActiveCfg = Release|Any CPU
{98335B23-E4B9-4CAD-9749-0DED32A659A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{98335B23-E4B9-4CAD-9749-0DED32A659A1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{98335B23-E4B9-4CAD-9749-0DED32A659A1}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{98335B23-E4B9-4CAD-9749-0DED32A659A1}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{98335B23-E4B9-4CAD-9749-0DED32A659A1}.Debug|x86.ActiveCfg = Debug|Any CPU
{98335B23-E4B9-4CAD-9749-0DED32A659A1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{98335B23-E4B9-4CAD-9749-0DED32A659A1}.Release|Any CPU.Build.0 = Release|Any CPU
{98335B23-E4B9-4CAD-9749-0DED32A659A1}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{98335B23-E4B9-4CAD-9749-0DED32A659A1}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{98335B23-E4B9-4CAD-9749-0DED32A659A1}.Release|x86.ActiveCfg = Release|Any CPU
{E69FD235-2042-43A4-9970-59CB29955B4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E69FD235-2042-43A4-9970-59CB29955B4E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E69FD235-2042-43A4-9970-59CB29955B4E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{E69FD235-2042-43A4-9970-59CB29955B4E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{E69FD235-2042-43A4-9970-59CB29955B4E}.Debug|x86.ActiveCfg = Debug|Any CPU
{E69FD235-2042-43A4-9970-59CB29955B4E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E69FD235-2042-43A4-9970-59CB29955B4E}.Release|Any CPU.Build.0 = Release|Any CPU
{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
{23D30B8C-04B1-4577-A604-ED27EA1E4A0E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{23D30B8C-04B1-4577-A604-ED27EA1E4A0E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{23D30B8C-04B1-4577-A604-ED27EA1E4A0E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
@ -247,8 +223,6 @@ Global
{520B3AA4-363A-497C-8C15-80423C5AFC85} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E}
{7C4F5973-0491-4028-B1DC-A9BA73FF9F77} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1}
{5F945B82-FE5F-425C-956C-8BC2F2020254} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1}
{98335B23-E4B9-4CAD-9749-0DED32A659A1} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E}
{E69FD235-2042-43A4-9970-59CB29955B4E} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1}
{23D30B8C-04B1-4577-A604-ED27EA1E4A0E} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E}
{5DE8E4D9-AACD-4B5F-819F-F091383FB996} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1}
{680D75ED-601F-4D86-B01B-1072D0C31B8C} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1}

26
Mvc.sln
View File

@ -53,10 +53,6 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "RazorWebSite", "test\WebSit
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "FormatterWebSite", "test\WebSites\FormatterWebSite\FormatterWebSite.kproj", "{62735776-46FF-4170-9392-02E128A69B89}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Mvc.HeaderValueAbstractions", "src\Microsoft.AspNet.Mvc.HeaderValueAbstractions\Microsoft.AspNet.Mvc.HeaderValueAbstractions.kproj", "{98335B23-E4B9-4CAD-9749-0DED32A659A1}"
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("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ModelBindingWebSite", "test\WebSites\ModelBindingWebSite\ModelBindingWebSite.kproj", "{EE1AB716-F102-4CA3-AD2C-214A44B459A0}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{FAD65E9C-3CF3-4F68-9757-C7358604030B}"
@ -340,26 +336,6 @@ Global
{62735776-46FF-4170-9392-02E128A69B89}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{62735776-46FF-4170-9392-02E128A69B89}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{62735776-46FF-4170-9392-02E128A69B89}.Release|x86.ActiveCfg = Release|Any CPU
{98335B23-E4B9-4CAD-9749-0DED32A659A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{98335B23-E4B9-4CAD-9749-0DED32A659A1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{98335B23-E4B9-4CAD-9749-0DED32A659A1}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{98335B23-E4B9-4CAD-9749-0DED32A659A1}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{98335B23-E4B9-4CAD-9749-0DED32A659A1}.Debug|x86.ActiveCfg = Debug|Any CPU
{98335B23-E4B9-4CAD-9749-0DED32A659A1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{98335B23-E4B9-4CAD-9749-0DED32A659A1}.Release|Any CPU.Build.0 = Release|Any CPU
{98335B23-E4B9-4CAD-9749-0DED32A659A1}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{98335B23-E4B9-4CAD-9749-0DED32A659A1}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{98335B23-E4B9-4CAD-9749-0DED32A659A1}.Release|x86.ActiveCfg = Release|Any CPU
{E69FD235-2042-43A4-9970-59CB29955B4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E69FD235-2042-43A4-9970-59CB29955B4E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E69FD235-2042-43A4-9970-59CB29955B4E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{E69FD235-2042-43A4-9970-59CB29955B4E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{E69FD235-2042-43A4-9970-59CB29955B4E}.Debug|x86.ActiveCfg = Debug|Any CPU
{E69FD235-2042-43A4-9970-59CB29955B4E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E69FD235-2042-43A4-9970-59CB29955B4E}.Release|Any CPU.Build.0 = Release|Any CPU
{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
{EE1AB716-F102-4CA3-AD2C-214A44B459A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EE1AB716-F102-4CA3-AD2C-214A44B459A0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EE1AB716-F102-4CA3-AD2C-214A44B459A0}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
@ -691,8 +667,6 @@ Global
{5F945B82-FE5F-425C-956C-8BC2F2020254} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1}
{B07CAF59-11ED-40E3-A5DB-E1178F84FA78} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
{62735776-46FF-4170-9392-02E128A69B89} = {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}
{EE1AB716-F102-4CA3-AD2C-214A44B459A0} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
{C6E5AFFA-890A-448F-8DE3-878B1D3C9FC7} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
{A353B17E-A940-4CE8-8BF9-179E24A9041F} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}

View File

@ -32,7 +32,7 @@
<ul>
@foreach (var response in Model.SupportedResponseFormats)
{
<li>@response.MediaType.RawValue - @response.Formatter.GetType().Name</li>
<li>@response.MediaType.ToString() - @response.Formatter.GetType().Name</li>
}
</ul>
}

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
@ -14,4 +14,9 @@
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>
<ProjectExtensions>
<VisualStudio>
<UserProperties project_1json__JSONSchema="http://www.asp.net/media/4878834/project.json" />
</VisualStudio>
</ProjectExtensions>
</Project>

View File

@ -6,6 +6,7 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNet.Mvc
{
@ -54,11 +55,12 @@ namespace Microsoft.AspNet.Mvc
// detached and stored in a separate file. If the receiving MUA writes
// the entity to a file, the suggested filename should be used as a
// basis for the actual filename, where possible.
var headerValue = ContentDispositionUtil.GetHeaderValue(FileDownloadName);
context.HttpContext.Response.Headers.Set("Content-Disposition", headerValue);
var cd = new ContentDispositionHeaderValue("attachment");
cd.SetHttpFileName(FileDownloadName);
context.HttpContext.Response.Headers.Set(HeaderNames.ContentDisposition, cd.ToString());
}
// We aren't flowing the cancellation token appropiately, see
// We aren't flowing the cancellation token appropriately, see
// https://github.com/aspnet/Mvc/issues/743 for details.
return WriteFileAsync(response, CancellationToken.None);
}
@ -74,193 +76,5 @@ namespace Microsoft.AspNet.Mvc
/// A <see cref="Task"/> that will complete when the file has been written to the response.
/// </returns>
protected abstract Task WriteFileAsync(HttpResponse response, CancellationToken cancellation);
// This is a temporary implementation until we have the right abstractions in HttpAbstractions.
internal static class ContentDispositionUtil
{
private const string HexDigits = "0123456789ABCDEF";
private static void AddByteToStringBuilder(byte b, StringBuilder builder)
{
builder.Append('%');
var i = b;
AddHexDigitToStringBuilder(i >> 4, builder);
AddHexDigitToStringBuilder(i % 16, builder);
}
private static void AddHexDigitToStringBuilder(int digit, StringBuilder builder)
{
builder.Append(HexDigits[digit]);
}
private static string CreateRfc2231HeaderValue(string filename)
{
var builder = new StringBuilder("attachment; filename*=UTF-8''");
var filenameBytes = Encoding.UTF8.GetBytes(filename);
foreach (var b in filenameBytes)
{
if (IsByteValidHeaderValueCharacter(b))
{
builder.Append((char)b);
}
else
{
AddByteToStringBuilder(b, builder);
}
}
return builder.ToString();
}
public static string GetHeaderValue(string fileName)
{
// If fileName contains any Unicode characters, encode according
// to RFC 2231 (with clarifications from RFC 5987)
foreach (var c in fileName)
{
if ((int)c > 127)
{
return CreateRfc2231HeaderValue(fileName);
}
}
return CreateNonUnicodeCharactersHeaderValue(fileName);
}
private static string CreateNonUnicodeCharactersHeaderValue(string fileName)
{
var escapedFileName = EscapeFileName(fileName);
return string.Format("attachment; filename={0}", escapedFileName);
}
private static string EscapeFileName(string fileName)
{
var hasToBeQuoted = false;
// We can't break the loop earlier because we need to check the
// whole name for \n, in which case we need to provide a special
// encoding.
for (var i = 0; i < fileName.Length; i++)
{
if (fileName[i] == '\n')
{
// See RFC 2047 for more details
return GetRfc2047Base64EncodedWord(fileName);
}
// Control characters = (octets 0 - 31) and DEL (127)
if (char.IsControl(fileName[i]))
{
hasToBeQuoted = true;
}
switch (fileName[i])
{
case '(':
case ')':
case '<':
case '>':
case '@':
case ',':
case ';':
case ':':
case '\\':
case '/':
case '[':
case ']':
case '?':
case '=':
case '{':
case '}':
case ' ':
case '\t':
case '"':
hasToBeQuoted = true;
break;
default:
break;
}
}
return hasToBeQuoted ? QuoteFileName(fileName) : fileName;
}
private static string QuoteFileName(string fileName)
{
var builder = new StringBuilder();
builder.Append("\"");
for (var i = 0; i < fileName.Length; i++)
{
switch (fileName[i])
{
case '\\':
// Escape \
builder.Append("\\\\");
break;
case '"':
// Escape "
builder.Append("\\\"");
break;
default:
builder.Append(fileName[i]);
break;
}
}
builder.Append("\"");
return builder.ToString();
}
private static string GetRfc2047Base64EncodedWord(string fileName)
{
// See RFC 2047 for details. Section 8 for examples.
const string charset = "utf-8";
// B means Base64
const string encoding = "B";
var fileNameBytes = Encoding.UTF8.GetBytes(fileName);
var base64EncodedFileName = Convert.ToBase64String(fileNameBytes);
// Encoded words are defined as "=?{charset}?{encoding}?{encpoded value}?="
return string.Format("\"=?{0}?{1}?{2}?=\"", charset, encoding, base64EncodedFileName);
}
// Application of RFC 2231 Encoding to Hypertext Transfer Protocol (HTTP) Header Fields, sec. 3.2
// http://greenbytes.de/tech/webdav/draft-reschke-rfc2231-in-http-latest.html
private static bool IsByteValidHeaderValueCharacter(byte b)
{
if ((byte)'0' <= b && b <= (byte)'9')
{
return true; // is digit
}
if ((byte)'a' <= b && b <= (byte)'z')
{
return true; // lowercase letter
}
if ((byte)'A' <= b && b <= (byte)'Z')
{
return true; // uppercase letter
}
switch (b)
{
case (byte)'-':
case (byte)'.':
case (byte)'_':
case (byte)'~':
case (byte)':':
case (byte)'!':
case (byte)'$':
case (byte)'&':
case (byte)'+':
return true;
}
return false;
}
}
}
}

View File

@ -4,8 +4,8 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNet.Mvc
{

View File

@ -5,8 +5,9 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
using Microsoft.AspNet.Http;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNet.Mvc
{
@ -62,10 +63,9 @@ namespace Microsoft.AspNet.Mvc
public virtual IOutputFormatter SelectFormatter(OutputFormatterContext formatterContext,
IEnumerable<IOutputFormatter> formatters)
{
var incomingAcceptHeader = HeaderParsingHelpers.GetAcceptHeaders(
formatterContext.ActionContext.HttpContext.Request.Accept);
var sortedAcceptHeaders = SortMediaTypeWithQualityHeaderValues(incomingAcceptHeader)
.Where(header => header.Quality != HttpHeaderUtilitites.NoMatch)
var incomingAcceptHeader = formatterContext.ActionContext.HttpContext.Request.GetTypedHeaders().Accept;
var sortedAcceptHeaders = SortMediaTypeHeaderValues(incomingAcceptHeader)
.Where(header => header.Quality != HeaderQuality.NoMatch)
.ToArray();
IOutputFormatter selectedFormatter = null;
@ -194,19 +194,19 @@ namespace Microsoft.AspNet.Mvc
return selectedFormatter;
}
private static MediaTypeWithQualityHeaderValue[] SortMediaTypeWithQualityHeaderValues
(IEnumerable<MediaTypeWithQualityHeaderValue> headerValues)
private static MediaTypeHeaderValue[] SortMediaTypeHeaderValues
(IEnumerable<MediaTypeHeaderValue> headerValues)
{
if (headerValues == null)
{
return new MediaTypeWithQualityHeaderValue[] { };
return new MediaTypeHeaderValue[] { };
}
// 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(headerValue =>
headerValue,
MediaTypeWithQualityHeaderValueComparer.QualityComparer)
MediaTypeHeaderValueComparer.QualityComparer)
.ToArray();
}

View File

@ -1,7 +1,7 @@
// 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.HeaderValueAbstractions;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNet.Mvc.Description
{

View File

@ -6,10 +6,10 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Routing;
using Microsoft.AspNet.Routing.Template;
using Microsoft.Net.Http.Headers;
using Microsoft.Framework.DependencyInjection;
namespace Microsoft.AspNet.Mvc.Description

View File

@ -3,7 +3,7 @@
using System;
using System.Collections.Generic;
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNet.Mvc.Description
{

View File

@ -4,7 +4,7 @@
using System;
using System.Collections.Generic;
using Microsoft.AspNet.Mvc.Description;
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNet.Mvc
{

View File

@ -4,7 +4,7 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNet.Mvc
{

View File

@ -4,7 +4,7 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNet.Mvc
{

View File

@ -4,7 +4,7 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNet.Mvc
{

View File

@ -9,7 +9,7 @@ using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.Core;
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
using Microsoft.Net.Http.Headers;
using Newtonsoft.Json;
namespace Microsoft.AspNet.Mvc

View File

@ -4,7 +4,7 @@
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
using Microsoft.Net.Http.Headers;
using Newtonsoft.Json;
namespace Microsoft.AspNet.Mvc

View File

@ -1,103 +0,0 @@
// 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>
/// Implementation of <see cref="IComparer{T}"/> that can compare accept media type header fields
/// based on their quality values (a.k.a q-values).
/// </summary>
public class MediaTypeWithQualityHeaderValueComparer : IComparer<MediaTypeWithQualityHeaderValue>
{
private static readonly MediaTypeWithQualityHeaderValueComparer _mediaTypeComparer =
new MediaTypeWithQualityHeaderValueComparer();
private MediaTypeWithQualityHeaderValueComparer()
{
}
public static MediaTypeWithQualityHeaderValueComparer QualityComparer
{
get { return _mediaTypeComparer; }
}
/// <inheritdoc />
/// <remarks>
/// Performs comparisons based on the arguments' quality values
/// (aka their "q-value"). Values with identical q-values are considered equal (i.e. the result is 0)
/// with the exception that subtype wildcards are considered less than specific media types and full
/// wildcards are considered less than subtype wildcards. This allows callers to sort a sequence of
/// <see cref="MediaTypeWithQualityHeaderValue"/> following their q-values in the order of specific
/// media types, subtype wildcards, and last any full wildcards.
/// </remarks>
public int Compare(MediaTypeWithQualityHeaderValue mediaType1, MediaTypeWithQualityHeaderValue mediaType2)
{
if (object.ReferenceEquals(mediaType1, mediaType2))
{
return 0;
}
var returnValue = CompareBasedOnQualityFactor(mediaType1, mediaType2);
if (returnValue == 0)
{
if (!mediaType1.MediaType.Equals(mediaType2.MediaType, StringComparison.OrdinalIgnoreCase))
{
if (mediaType1.MediaTypeRange == MediaTypeHeaderValueRange.AllMediaRange)
{
return -1;
}
else if (mediaType2.MediaTypeRange == MediaTypeHeaderValueRange.AllMediaRange)
{
return 1;
}
else if (mediaType1.MediaTypeRange == MediaTypeHeaderValueRange.SubtypeMediaRange &&
mediaType2.MediaTypeRange != MediaTypeHeaderValueRange.SubtypeMediaRange)
{
return -1;
}
else if (mediaType1.MediaTypeRange != MediaTypeHeaderValueRange.SubtypeMediaRange &&
mediaType2.MediaTypeRange == MediaTypeHeaderValueRange.SubtypeMediaRange)
{
return 1;
}
}
else if (!mediaType1.MediaSubType.Equals(mediaType2.MediaSubType, StringComparison.OrdinalIgnoreCase))
{
if (mediaType1.MediaTypeRange == MediaTypeHeaderValueRange.SubtypeMediaRange)
{
return -1;
}
else if (mediaType2.MediaTypeRange == MediaTypeHeaderValueRange.SubtypeMediaRange)
{
return 1;
}
}
}
return returnValue;
}
private static int CompareBasedOnQualityFactor(MediaTypeWithQualityHeaderValue mediaType1,
MediaTypeWithQualityHeaderValue mediaType2)
{
var mediaType1Quality = mediaType1.Quality ?? HttpHeaderUtilitites.Match;
var mediaType2Quality = mediaType2.Quality ?? HttpHeaderUtilitites.Match;
var qualityDifference = mediaType1Quality - mediaType2Quality;
if (qualityDifference < 0)
{
return -1;
}
else if (qualityDifference > 0)
{
return 1;
}
return 0;
}
}
}

View File

@ -6,8 +6,9 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc.Core;
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNet.Mvc
{
@ -102,7 +103,7 @@ namespace Microsoft.AspNet.Mvc
public virtual Encoding SelectCharacterEncoding([NotNull] OutputFormatterContext context)
{
var request = context.ActionContext.HttpContext.Request;
var encoding = MatchAcceptCharacterEncoding(request.AcceptCharset);
var encoding = MatchAcceptCharacterEncoding(request.GetTypedHeaders().AcceptCharset);
if (encoding == null)
{
// Match based on request acceptHeader.
@ -190,7 +191,7 @@ namespace Microsoft.AspNet.Mvc
context.SelectedContentType = context.SelectedContentType ?? selectedMediaType;
var response = context.ActionContext.HttpContext.Response;
response.ContentType = selectedMediaType.RawValue;
response.ContentType = selectedMediaType.ToString();
}
/// <summary>
@ -200,16 +201,13 @@ namespace Microsoft.AspNet.Mvc
/// <returns>A task which can write the response body.</returns>
public abstract Task WriteResponseBodyAsync([NotNull] OutputFormatterContext context);
private Encoding MatchAcceptCharacterEncoding(string acceptCharsetHeader)
private Encoding MatchAcceptCharacterEncoding(IList<StringWithQualityHeaderValue> acceptCharsetHeaders)
{
var acceptCharsetHeaders = HeaderParsingHelpers
.GetAcceptCharsetHeaders(acceptCharsetHeader);
if (acceptCharsetHeaders != null && acceptCharsetHeaders.Count > 0)
{
var sortedAcceptCharsetHeaders = acceptCharsetHeaders
.Where(acceptCharset =>
acceptCharset.Quality != HttpHeaderUtilitites.NoMatch)
acceptCharset.Quality != HeaderQuality.NoMatch)
.OrderByDescending(
m => m, StringWithQualityHeaderValueComparer.QualityComparer);

View File

@ -3,7 +3,7 @@
using System;
using System.Text;
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNet.Mvc
{

View File

@ -1,72 +0,0 @@
// 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>
/// Implementation of <see cref="IComparer{T}"/> that can compare content negotiation header fields
/// based on their quality values (a.k.a q-values). This applies to values used in accept-charset,
/// accept-encoding, accept-language and related header fields with similar syntax rules. See
/// <see cref="MediaTypeWithQualityHeaderValueComparer"/> for a comparer for media type
/// q-values.
/// </summary>
internal class StringWithQualityHeaderValueComparer : IComparer<StringWithQualityHeaderValue>
{
private static readonly StringWithQualityHeaderValueComparer _qualityComparer =
new StringWithQualityHeaderValueComparer();
private StringWithQualityHeaderValueComparer()
{
}
public static StringWithQualityHeaderValueComparer QualityComparer
{
get { return _qualityComparer; }
}
/// <summary>
/// Compares two <see cref="StringWithQualityHeaderValue"/> based on their quality value
/// (a.k.a their "q-value").
/// Values with identical q-values are considered equal (i.e the result is 0) with the exception of wild-card
/// values (i.e. a value of "*") which are considered less than non-wild-card values. This allows to sort
/// a sequence of <see cref="StringWithQualityHeaderValue"/> following their q-values ending up with any
/// wild-cards at the end.
/// </summary>
/// <param name="stringWithQuality1">The first value to compare.</param>
/// <param name="stringWithQuality2">The second value to compare</param>
/// <returns>The result of the comparison.</returns>
public int Compare([NotNull] StringWithQualityHeaderValue stringWithQuality1,
[NotNull] StringWithQualityHeaderValue stringWithQuality2)
{
var quality1 = stringWithQuality1.Quality ?? HttpHeaderUtilitites.Match;
var quality2 = stringWithQuality2.Quality ?? HttpHeaderUtilitites.Match;
var qualityDifference = quality1 - quality2;
if (qualityDifference < 0)
{
return -1;
}
else if (qualityDifference > 0)
{
return 1;
}
if (!String.Equals(stringWithQuality1.Value, stringWithQuality2.Value, StringComparison.OrdinalIgnoreCase))
{
if (String.Equals(stringWithQuality1.Value, "*", StringComparison.Ordinal))
{
return -1;
}
else if (String.Equals(stringWithQuality2.Value, "*", StringComparison.Ordinal))
{
return 1;
}
}
return 0;
}
}
}

View File

@ -3,7 +3,7 @@
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNet.Mvc
{

View File

@ -10,7 +10,7 @@ using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNet.Mvc
{

View File

@ -4,7 +4,7 @@
using System;
using System.IO;
using System.Xml;
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNet.Mvc
{

View File

@ -10,7 +10,7 @@ using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Serialization;
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNet.Mvc
{

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
@ -14,4 +14,9 @@
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>
<ProjectExtensions>
<VisualStudio>
<UserProperties project_1json__JSONSchema="http://www.asp.net/media/4878834/project.json" />
</VisualStudio>
</ProjectExtensions>
</Project>

View File

@ -7,7 +7,7 @@
"dependencies": {
"Microsoft.AspNet.FileSystems": "1.0.0-*",
"Microsoft.AspNet.Hosting": "1.0.0-*",
"Microsoft.AspNet.Mvc.HeaderValueAbstractions": "1.0.0-*",
"Microsoft.AspNet.Http.Extensions": "1.0.0-*",
"Microsoft.AspNet.Mvc.Common": { "version": "6.0.0-*", "type": "build" },
"Microsoft.AspNet.Mvc.ModelBinding": "6.0.0-*",
"Microsoft.AspNet.Routing": "1.0.0-*",

View File

@ -1,56 +0,0 @@
// 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;
namespace Microsoft.AspNet.Mvc.HeaderValueAbstractions
{
public static class HeaderParsingHelpers
{
public static IList<MediaTypeWithQualityHeaderValue> GetAcceptHeaders(string acceptHeader)
{
if (string.IsNullOrEmpty(acceptHeader))
{
return null;
}
var acceptHeaderCollection = new List<MediaTypeWithQualityHeaderValue>();
foreach (var item in acceptHeader.Split(','))
{
MediaTypeWithQualityHeaderValue parsedAcceptHeader;
// If we are unable to parse any of the Accept Headers, we ignore them completely.
if (!MediaTypeWithQualityHeaderValue.TryParse(item, out parsedAcceptHeader))
{
return null;
}
acceptHeaderCollection.Add(parsedAcceptHeader);
}
return acceptHeaderCollection;
}
public static IList<StringWithQualityHeaderValue> GetAcceptCharsetHeaders(string acceptCharsetHeader)
{
if (string.IsNullOrEmpty(acceptCharsetHeader))
{
return null;
}
var acceptCharsetHeaderCollection = new List<StringWithQualityHeaderValue>();
foreach (var item in acceptCharsetHeader.Split(','))
{
StringWithQualityHeaderValue parsedAcceptCharsetHeader;
// If we are unable to parse any of the Accept-Charset Headers, we ignore them completely.
if (!StringWithQualityHeaderValue.TryParse(item, out parsedAcceptCharsetHeader))
{
return null;
}
acceptCharsetHeaderCollection.Add(parsedAcceptCharsetHeader);
}
return acceptCharsetHeaderCollection;
}
}
}

View File

@ -1,18 +0,0 @@
// 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.
namespace Microsoft.AspNet.Mvc.HeaderValueAbstractions
{
public static class HttpHeaderUtilitites
{
/// <summary>
/// Quality factor to indicate a perfect match.
/// </summary>
public const double Match = 1.0;
/// <summary>
/// Quality factor to indicate no match.
/// </summary>
public const double NoMatch = 0.0;
}
}

View File

@ -1,197 +0,0 @@
// 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.Text;
namespace Microsoft.AspNet.Mvc.HeaderValueAbstractions
{
public class MediaTypeHeaderValue
{
public string Charset { get; set; }
public string MediaType { get; set; }
public string MediaSubType { get; set; }
public MediaTypeHeaderValueRange MediaTypeRange { get; set; }
public string RawValue
{
get
{
var stringBuilder = new StringBuilder();
stringBuilder.Append(MediaType);
stringBuilder.Append('/');
stringBuilder.Append(MediaSubType);
if (!string.IsNullOrEmpty(Charset))
{
stringBuilder.Append(";charset=");
stringBuilder.Append(Charset);
}
foreach (var parameter in Parameters)
{
if (string.Equals(parameter.Key, "charset", System.StringComparison.OrdinalIgnoreCase))
{
continue;
}
stringBuilder.Append(";");
stringBuilder.Append(parameter.Key);
stringBuilder.Append("=");
stringBuilder.Append(parameter.Value);
}
return stringBuilder.ToString();
}
}
public IDictionary<string, string> Parameters { get; set; }
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 false;
}
var inputArray = input.Split(new[] { ';' }, 2);
var mediaTypeParts = inputArray[0].Split('/');
if (mediaTypeParts.Length != 2)
{
return false;
}
var mediaType = mediaTypeParts[0].Trim();
var mediaSubType = mediaTypeParts[1].Trim();
var mediaTypeRange = MediaTypeHeaderValueRange.None;
if (mediaType == "*" && mediaSubType == "*")
{
mediaTypeRange = MediaTypeHeaderValueRange.AllMediaRange;
}
else if (mediaSubType == "*")
{
mediaTypeRange = MediaTypeHeaderValueRange.SubtypeMediaRange;
}
Dictionary<string, string> parameters = null;
string charset = null;
if (inputArray.Length == 2)
{
parameters = ParseParameters(inputArray[1]);
parameters.TryGetValue("charset", out charset);
}
headerValue = new MediaTypeHeaderValue()
{
MediaType = mediaType,
MediaSubType = mediaSubType,
MediaTypeRange = mediaTypeRange,
Charset = charset,
Parameters = parameters ?? new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase),
};
return true;
}
protected static Dictionary<string, string> ParseParameters(string inputString)
{
var acceptParameters = inputString.Split(';');
var parameterNameValue = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
foreach (var parameter in acceptParameters)
{
var index = parameter.Split('=');
if (index.Length == 2)
{
parameterNameValue.Add(index[0].Trim(), index[1].Trim());
}
}
return parameterNameValue;
}
/// <summary>
/// Determines whether this instance is a subset of passed <see cref="MediaTypeHeaderValue"/>.
/// If the media type and media type parameters of this media type are all present
/// and match those of <paramref name="otherMediaType"/> then it is a match even though
/// <paramref name="otherMediaType"/> may have additional parameters.
/// </summary>
/// <param name="mediaType">The first media type.</param>
/// <param name="otherMediaType">The second media type.</param>
/// <returns><c>true</c> if this is a subset of <paramref name="otherMediaType"/>; false otherwise.</returns>
public bool IsSubsetOf(MediaTypeHeaderValue otherMediaType)
{
if (otherMediaType == null)
{
return false;
}
if (!MediaType.Equals(otherMediaType.MediaType, StringComparison.OrdinalIgnoreCase))
{
if (otherMediaType.MediaTypeRange != MediaTypeHeaderValueRange.AllMediaRange)
{
return false;
}
}
else if (!MediaSubType.Equals(otherMediaType.MediaSubType, StringComparison.OrdinalIgnoreCase))
{
if (otherMediaType.MediaTypeRange != MediaTypeHeaderValueRange.SubtypeMediaRange)
{
return false;
}
}
if (Parameters != null)
{
if (Parameters.Count != 0 &&
(otherMediaType.Parameters == null || otherMediaType.Parameters.Count == 0))
{
return false;
}
// So far we either have a full match or a subset match. Now check that all of
// mediaType1's parameters are present and equal in mediatype2
if (!MatchParameters(Parameters, otherMediaType.Parameters))
{
return false;
}
}
return true;
}
private static bool MatchParameters(IDictionary<string, string> parameters1,
IDictionary<string, string> parameters2)
{
foreach (var parameterKey in parameters1.Keys)
{
string parameterValue2 = null;
if (!parameters2.TryGetValue(parameterKey, out parameterValue2))
{
return false;
}
if (!string.Equals(parameterValue2, parameters1[parameterKey], StringComparison.OrdinalIgnoreCase))
{
return false;
}
}
return true;
}
}
}

View File

@ -1,23 +0,0 @@
// 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.
namespace Microsoft.AspNet.Mvc
{
public enum MediaTypeHeaderValueRange
{
/// <summary>
/// Not a media type range
/// </summary>
None = 0,
/// <summary>
/// A subtype media range, e.g. "application/*".
/// </summary>
SubtypeMediaRange,
/// <summary>
/// An all media range, e.g. "*/*".
/// </summary>
AllMediaRange,
}
}

View File

@ -1,62 +0,0 @@
// 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.Globalization;
namespace Microsoft.AspNet.Mvc.HeaderValueAbstractions
{
public class MediaTypeWithQualityHeaderValue : MediaTypeHeaderValue
{
public double? Quality { get; private set; }
public static bool TryParse(string input, out MediaTypeWithQualityHeaderValue headerValue)
{
MediaTypeHeaderValue mediaTypeHeaderValue;
if (!MediaTypeHeaderValue.TryParse(input, out mediaTypeHeaderValue))
{
headerValue = null;
return false;
}
var quality = HttpHeaderUtilitites.Match;
string qualityStringValue;
if (mediaTypeHeaderValue.Parameters.TryGetValue("q", out qualityStringValue))
{
if (!double.TryParse(
qualityStringValue,
NumberStyles.AllowLeadingWhite | NumberStyles.AllowDecimalPoint |
NumberStyles.AllowTrailingWhite,
NumberFormatInfo.InvariantInfo,
out quality))
{
headerValue = null;
return false;
}
}
headerValue = new MediaTypeWithQualityHeaderValue()
{
MediaType = mediaTypeHeaderValue.MediaType,
MediaSubType = mediaTypeHeaderValue.MediaSubType,
MediaTypeRange = mediaTypeHeaderValue.MediaTypeRange,
Charset = mediaTypeHeaderValue.Charset,
Parameters = mediaTypeHeaderValue.Parameters,
Quality = quality,
};
return true;
}
public static new MediaTypeWithQualityHeaderValue Parse(string input)
{
MediaTypeWithQualityHeaderValue headerValue = null;
if (!MediaTypeWithQualityHeaderValue.TryParse(input, out headerValue))
{
throw new ArgumentException(Resources.FormatInvalidAcceptHeader(input));
}
return headerValue;
}
}
}

View File

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.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>98335b23-e4b9-4cad-9749-0ded32a659a1</ProjectGuid>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

View File

@ -1,78 +0,0 @@
// <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. Accept Charset '{0}' could not be parsed.
/// </summary>
internal static string InvalidAcceptCharset
{
get { return GetString("InvalidAcceptCharset"); }
}
/// <summary>
/// Invalid Argument. Accept Charset '{0}' could not be parsed.
/// </summary>
internal static string FormatInvalidAcceptCharset(object p0)
{
return string.Format(CultureInfo.CurrentCulture, GetString("InvalidAcceptCharset"), p0);
}
/// <summary>
/// Invalid Argument. Accept Header '{0}' could not be parsed.
/// </summary>
internal static string InvalidAcceptHeader
{
get { return GetString("InvalidAcceptHeader"); }
}
/// <summary>
/// Invalid Argument. Accept Header '{0}' could not be parsed.
/// </summary>
internal static string FormatInvalidAcceptHeader(object p0)
{
return string.Format(CultureInfo.CurrentCulture, GetString("InvalidAcceptHeader"), p0);
}
/// <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;
}
}
}

View File

@ -1,129 +0,0 @@
<?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="InvalidAcceptCharset" xml:space="preserve">
<value>Invalid Argument. Accept Charset '{0}' could not be parsed.</value>
</data>
<data name="InvalidAcceptHeader" xml:space="preserve">
<value>Invalid Argument. Accept Header '{0}' could not be parsed.</value>
</data>
<data name="InvalidContentType" xml:space="preserve">
<value>Invalid Argument. Content type '{0}' could not be parsed.</value>
</data>
</root>

View File

@ -1,65 +0,0 @@
// 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.Globalization;
namespace Microsoft.AspNet.Mvc.HeaderValueAbstractions
{
public class StringWithQualityHeaderValue
{
public double? Quality { get; set; }
public string RawValue { get; set; }
public string Value { get; set; }
public static bool TryParse(string input, out StringWithQualityHeaderValue headerValue)
{
var inputArray = input.Split(new[] { ';' }, 2);
var value = inputArray[0].Trim();
// Unspecified q factor value is equal to a match.
var quality = HttpHeaderUtilitites.Match;
if (inputArray.Length > 1)
{
var parameter = inputArray[1].Trim();
var nameValuePair = parameter.Split(new[] { '=' }, 2);
if (nameValuePair.Length > 1 && nameValuePair[0].Trim().Equals("q"))
{
if (!double.TryParse(
nameValuePair[1],
NumberStyles.AllowLeadingWhite | NumberStyles.AllowDecimalPoint |
NumberStyles.AllowTrailingWhite,
NumberFormatInfo.InvariantInfo,
out quality))
{
headerValue = null;
return false;
}
}
}
var stringWithQualityHeader = new StringWithQualityHeaderValue()
{
Quality = quality,
Value = value,
RawValue = input
};
headerValue = stringWithQualityHeader;
return true;
}
public static StringWithQualityHeaderValue Parse(string input)
{
StringWithQualityHeaderValue headerValue;
if (!TryParse(input, out headerValue))
{
throw new ArgumentException(Resources.FormatInvalidAcceptCharset(input));
}
return headerValue;
}
}
}

View File

@ -1,16 +0,0 @@
{
"description": "Temporary abstractions for working with header values in ASP.NET MVC. These abstractions will be replaced by core HTTP abstractions in ASP.NET in a future release.",
"version": "1.0.0-*",
"dependencies": { },
"frameworks": {
"aspnet50": { },
"aspnetcore50": {
"dependencies": {
"System.Collections": "4.0.10-beta-*",
"System.Diagnostics.Debug": "4.0.10-beta-*",
"System.Resources.ResourceManager": "4.0.0-beta-*",
"System.Runtime.Extensions": "4.0.10-beta-*"
}
}
}
}

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
@ -14,4 +14,9 @@
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>
<ProjectExtensions>
<VisualStudio>
<UserProperties project_1json__JSONSchema="http://www.asp.net/media/4878834/project.json" />
</VisualStudio>
</ProjectExtensions>
</Project>

View File

@ -3,7 +3,7 @@
using System.Globalization;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNet.Mvc.ModelBinding
{

View File

@ -7,8 +7,8 @@
"dependencies": {
"Microsoft.AspNet.Http": "1.0.0-*",
"Microsoft.AspNet.Mvc.Common": { "version": "6.0.0-*", "type": "build" },
"Microsoft.AspNet.Mvc.HeaderValueAbstractions": "1.0.0-*",
"Microsoft.Framework.DependencyInjection": "1.0.0-*",
"Microsoft.Net.Http.Headers": "1.0.0-*",
"Newtonsoft.Json": "6.0.6"
},
"frameworks": {

View File

@ -319,27 +319,11 @@ namespace System.Net.Http.Formatting
for (var i = 0; i < supportedMediaTypes.Count; i++)
{
var supportedMediaType = supportedMediaTypes[i];
MediaTypeHeaderValueRange range;
MediaTypeFormatterMatchRanking ranking;
if (supportedMediaType != null &&
acceptMediaTypeValue.Quality != FormattingUtilities.NoMatch &&
supportedMediaType.IsSubsetOf(acceptMediaTypeValue, out range))
supportedMediaType.IsSubsetOf(acceptMediaTypeValue, out ranking))
{
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,

View File

@ -29,7 +29,7 @@ namespace System.Net.Http.Formatting
/// <returns><c>true</c> if this is a subset of <paramref name="mediaType2"/>; false otherwise.</returns>
public static bool IsSubsetOf(this MediaTypeHeaderValue mediaType1, MediaTypeHeaderValue mediaType2)
{
MediaTypeHeaderValueRange mediaType2Range;
MediaTypeFormatterMatchRanking mediaType2Range;
return IsSubsetOf(mediaType1, mediaType2, out mediaType2Range);
}
@ -52,37 +52,41 @@ namespace System.Net.Http.Formatting
public static bool IsSubsetOf(
this MediaTypeHeaderValue mediaType1,
MediaTypeHeaderValue mediaType2,
out MediaTypeHeaderValueRange mediaType2Range)
out MediaTypeFormatterMatchRanking mediaType2Range)
{
// Performance-sensitive
Debug.Assert(mediaType1 != null);
if (mediaType2 == null)
{
mediaType2Range = MediaTypeHeaderValueRange.None;
mediaType2Range = MediaTypeFormatterMatchRanking.None;
return false;
}
var parsedMediaType1 = new ParsedMediaTypeHeaderValue(mediaType1);
var parsedMediaType2 = new ParsedMediaTypeHeaderValue(mediaType2);
mediaType2Range = parsedMediaType2.IsAllMediaRange ? MediaTypeHeaderValueRange.AllMediaRange :
parsedMediaType2.IsSubtypeMediaRange ? MediaTypeHeaderValueRange.SubtypeMediaRange :
MediaTypeHeaderValueRange.None;
mediaType2Range = parsedMediaType2.IsAllMediaRange ? MediaTypeFormatterMatchRanking.MatchOnRequestAcceptHeaderAllMediaRange :
parsedMediaType2.IsSubtypeMediaRange ? MediaTypeFormatterMatchRanking.MatchOnRequestAcceptHeaderSubtypeMediaRange :
MediaTypeFormatterMatchRanking.None;
if (!parsedMediaType1.TypesEqual(ref parsedMediaType2))
{
if (mediaType2Range != MediaTypeHeaderValueRange.AllMediaRange)
if (mediaType2Range != MediaTypeFormatterMatchRanking.MatchOnRequestAcceptHeaderAllMediaRange)
{
return false;
}
}
else if (!parsedMediaType1.SubTypesEqual(ref parsedMediaType2))
{
if (mediaType2Range != MediaTypeHeaderValueRange.SubtypeMediaRange)
if (mediaType2Range != MediaTypeFormatterMatchRanking.MatchOnRequestAcceptHeaderSubtypeMediaRange)
{
return false;
}
}
else
{
mediaType2Range = MediaTypeFormatterMatchRanking.MatchOnRequestAcceptHeaderLiteral;
}
// So far we either have a full match or a subset match. Now check that all of
// mediaType1's parameters are present and equal in mediatype2

View File

@ -7,7 +7,7 @@ using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNet.HttpFeature;
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNet.Mvc.WebApiCompatShim
{

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
@ -14,4 +14,9 @@
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>
<ProjectExtensions>
<VisualStudio>
<UserProperties project_1json__JSONSchema="http://www.asp.net/media/4878834/project.json" />
</VisualStudio>
</ProjectExtensions>
</Project>

View File

@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.PipelineCore;
using Microsoft.AspNet.PipelineCore.Collections;
using Microsoft.AspNet.Routing;
using Microsoft.AspNet.Testing;
@ -21,8 +22,7 @@ namespace Microsoft.AspNet.Mvc
{
// Arrange
var expectedUrl = "testAction";
var response = GetMockedHttpResponseObject();
var httpContext = GetHttpContext(response);
var httpContext = GetHttpContext();
var actionContext = GetActionContext(httpContext);
var urlHelper = GetMockUrlHelper(expectedUrl);
@ -37,16 +37,15 @@ namespace Microsoft.AspNet.Mvc
await result.ExecuteResultAsync(actionContext);
// Assert
Assert.Equal(201, response.StatusCode);
Assert.Equal(expectedUrl, response.Headers["Location"]);
Assert.Equal(201, httpContext.Response.StatusCode);
Assert.Equal(expectedUrl, httpContext.Response.Headers["Location"]);
}
[Fact]
public async Task CreatedAtActionResult_ThrowsOnNullUrl()
{
// Arrange
var response = GetMockedHttpResponseObject();
var httpContext = GetHttpContext(response);
var httpContext = GetHttpContext();
var actionContext = GetActionContext(httpContext);
var urlHelper = GetMockUrlHelper(returnValue: null);
@ -60,7 +59,7 @@ namespace Microsoft.AspNet.Mvc
// Act & Assert
await ExceptionAssert.ThrowsAsync<InvalidOperationException>(
async () => await result.ExecuteResultAsync(actionContext),
async () => await result.ExecuteResultAsync(actionContext),
"No route matches the supplied values.");
}
@ -85,18 +84,15 @@ namespace Microsoft.AspNet.Mvc
new ActionDescriptor());
}
private static HttpContext GetHttpContext(HttpResponse response)
private static HttpContext GetHttpContext()
{
var httpContext = new Mock<HttpContext>();
httpContext.Setup(o => o.Response)
.Returns(response);
httpContext.Setup(o => o.RequestServices.GetService(typeof(IOutputFormattersProvider)))
.Returns(new TestOutputFormatterProvider());
httpContext.Setup(o => o.Request.PathBase)
.Returns(new PathString(""));
return httpContext.Object;
var httpContext = new DefaultHttpContext();
httpContext.Request.PathBase = new PathString("");
httpContext.Response.Body = new MemoryStream();
var services = new Mock<IServiceProvider>();
services.Setup(p => p.GetService(typeof(IOutputFormattersProvider))).Returns(new TestOutputFormatterProvider());
httpContext.RequestServices = services.Object;
return httpContext;
}
private static IUrlHelper GetMockUrlHelper(string returnValue)

View File

@ -6,7 +6,7 @@ using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.PipelineCore.Collections;
using Microsoft.AspNet.PipelineCore;
using Microsoft.AspNet.Routing;
using Microsoft.AspNet.Testing;
using Moq;
@ -41,8 +41,7 @@ namespace Microsoft.AspNet.Mvc
{
// Arrange
var expectedUrl = "testAction";
var response = GetMockedHttpResponseObject();
var httpContext = GetHttpContext(response);
var httpContext = GetHttpContext();
var actionContext = GetActionContext(httpContext);
var urlHelper = GetMockUrlHelper(expectedUrl);
@ -52,16 +51,15 @@ namespace Microsoft.AspNet.Mvc
await result.ExecuteResultAsync(actionContext);
// Assert
Assert.Equal(201, response.StatusCode);
Assert.Equal(expectedUrl, response.Headers["Location"]);
Assert.Equal(201, httpContext.Response.StatusCode);
Assert.Equal(expectedUrl, httpContext.Response.Headers["Location"]);
}
[Fact]
public async Task CreatedAtRouteResult_ThrowsOnNullUrl()
{
// Arrange
var response = GetMockedHttpResponseObject();
var httpContext = GetHttpContext(response);
var httpContext = GetHttpContext();
var actionContext = GetActionContext(httpContext);
var urlHelper = GetMockUrlHelper(returnValue: null);
@ -78,17 +76,6 @@ namespace Microsoft.AspNet.Mvc
"No route matches the supplied values.");
}
private static HttpResponse GetMockedHttpResponseObject()
{
var stream = new MemoryStream();
var httpResponse = new Mock<HttpResponse>();
httpResponse.SetupProperty(o => o.StatusCode);
httpResponse.Setup(o => o.Headers).Returns(
new HeaderDictionary(new Dictionary<string, string[]>()));
httpResponse.SetupGet(o => o.Body).Returns(stream);
return httpResponse.Object;
}
private static ActionContext GetActionContext(HttpContext httpContext)
{
var routeData = new RouteData();
@ -99,16 +86,21 @@ namespace Microsoft.AspNet.Mvc
new ActionDescriptor());
}
private static HttpContext GetHttpContext(HttpResponse response)
private static HttpContext GetHttpContext()
{
var httpContext = new Mock<HttpContext>();
var realContext = new DefaultHttpContext();
var request = realContext.Request;
request.PathBase = new PathString("");
var response = realContext.Response;
response.Body = new MemoryStream();
httpContext.Setup(o => o.Request)
.Returns(request);
httpContext.Setup(o => o.Response)
.Returns(response);
httpContext.Setup(o => o.RequestServices.GetService(typeof(IOutputFormattersProvider)))
.Returns(new TestOutputFormatterProvider());
httpContext.Setup(o => o.Request.PathBase)
.Returns(new PathString(""));
return httpContext.Object;
}

View File

@ -5,7 +5,7 @@ using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.PipelineCore.Collections;
using Microsoft.AspNet.PipelineCore;
using Microsoft.AspNet.Routing;
using Moq;
using Xunit;
@ -32,8 +32,7 @@ namespace Microsoft.AspNet.Mvc
{
// Arrange
var location = "/test/";
var response = GetMockedHttpResponseObject();
var httpContext = GetHttpContext(response);
var httpContext = GetHttpContext();
var actionContext = GetActionContext(httpContext);
var result = new CreatedResult(location, "testInput");
@ -41,19 +40,8 @@ namespace Microsoft.AspNet.Mvc
await result.ExecuteResultAsync(actionContext);
// Assert
Assert.Equal(201, response.StatusCode);
Assert.Equal(location, response.Headers["Location"]);
}
private static HttpResponse GetMockedHttpResponseObject()
{
var stream = new MemoryStream();
var httpResponse = new Mock<HttpResponse>();
httpResponse.SetupProperty(o => o.StatusCode);
httpResponse.Setup(o => o.Headers).Returns(
new HeaderDictionary(new Dictionary<string, string[]>()));
httpResponse.SetupGet(o => o.Body).Returns(stream);
return httpResponse.Object;
Assert.Equal(201, httpContext.Response.StatusCode);
Assert.Equal(location, httpContext.Response.Headers["Location"]);
}
private static ActionContext GetActionContext(HttpContext httpContext)
@ -66,16 +54,21 @@ namespace Microsoft.AspNet.Mvc
new ActionDescriptor());
}
private static HttpContext GetHttpContext(HttpResponse response)
private static HttpContext GetHttpContext()
{
var httpContext = new Mock<HttpContext>();
var realContext = new DefaultHttpContext();
var request = realContext.Request;
request.PathBase = new PathString("");
var response = realContext.Response;
response.Body = new MemoryStream();
httpContext.Setup(o => o.Request)
.Returns(request);
httpContext.Setup(o => o.Response)
.Returns(response);
httpContext.Setup(o => o.RequestServices.GetService(typeof(IOutputFormattersProvider)))
.Returns(new TestOutputFormatterProvider());
httpContext.Setup(o => o.Request.PathBase)
.Returns(new PathString(""));
return httpContext.Object;
}

View File

@ -6,7 +6,9 @@ using System.Net.Mime;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.PipelineCore;
using Microsoft.AspNet.Routing;
using Microsoft.Net.Http.Headers;
using Moq;
using Xunit;
@ -30,13 +32,8 @@ namespace Microsoft.AspNet.Mvc
// See comment in FileResult.cs detailing how the FileDownloadName should be encoded.
// Arrange
var httpContext = new Mock<HttpContext>();
httpContext.SetupSet(c => c.Response.ContentType = "application/my-type").Verifiable();
httpContext
.Setup(c => c.Response.Headers.Set("Content-Disposition", @"attachment; filename=""some\\file"""))
.Verifiable();
var actionContext = CreateActionContext(httpContext.Object);
var httpContext = new DefaultHttpContext();
var actionContext = CreateActionContext(httpContext);
var result = new EmptyFileResult("application/my-type")
{
@ -48,22 +45,17 @@ namespace Microsoft.AspNet.Mvc
// Assert
Assert.True(result.WasWriteFileCalled);
httpContext.Verify();
Assert.Equal("application/my-type", httpContext.Response.Headers["Content-Type"]);
Assert.Equal(@"attachment; filename=""some\\file""; filename*=UTF-8''some%5Cfile", httpContext.Response.Headers["Content-Disposition"]);
}
[Fact]
public async Task ContentDispositionHeader_IsEncodedCorrectly_ForUnicodeCharacters()
{
// Arrange
var httpContext = new Mock<HttpContext>();
httpContext.SetupSet(c => c.Response.ContentType = "application/my-type").Verifiable();
httpContext
.Setup(c => c.Response.Headers.Set(
"Content-Disposition",
@"attachment; filename*=UTF-8''ABCXYZabcxyz012789!%40%23$%25%5E&%2A%28%29-%3D_+.:~%CE%94"))
.Verifiable();
var actionContext = CreateActionContext(httpContext.Object);
var httpContext = new DefaultHttpContext();
var actionContext = CreateActionContext(httpContext);
var result = new EmptyFileResult("application/my-type")
{
@ -75,7 +67,9 @@ namespace Microsoft.AspNet.Mvc
// Assert
Assert.True(result.WasWriteFileCalled);
httpContext.Verify();
Assert.Equal("application/my-type", httpContext.Response.Headers["Content-Type"]);
Assert.Equal(@"attachment; filename=""ABCXYZabcxyz012789!@#$%^&*()-=_+.:~_""; filename*=UTF-8''ABCXYZabcxyz012789!%40#$%25^&%2A%28%29-%3D_+.%3A~%CE%94",
httpContext.Response.Headers["Content-Disposition"]);
}
[Fact]
@ -102,13 +96,8 @@ namespace Microsoft.AspNet.Mvc
public async Task ExecuteResultAsync_SetsContentDisposition_IfSpecified()
{
// Arrange
var httpContext = new Mock<HttpContext>(MockBehavior.Strict);
httpContext.SetupSet(c => c.Response.ContentType = "application/my-type").Verifiable();
httpContext
.Setup(c => c.Response.Headers.Set("Content-Disposition", "attachment; filename=filename.ext"))
.Verifiable();
var actionContext = CreateActionContext(httpContext.Object);
var httpContext = new DefaultHttpContext();
var actionContext = CreateActionContext(httpContext);
var result = new EmptyFileResult("application/my-type")
{
@ -120,7 +109,8 @@ namespace Microsoft.AspNet.Mvc
// Assert
Assert.True(result.WasWriteFileCalled);
httpContext.Verify();
Assert.Equal("application/my-type", httpContext.Response.ContentType);
Assert.Equal("attachment; filename=filename.ext; filename*=UTF-8''filename.ext", httpContext.Response.Headers["Content-Disposition"]);
}
public static TheoryData<string, string> ContentDispositionData
@ -130,49 +120,54 @@ namespace Microsoft.AspNet.Mvc
return new TheoryData<string, string>
{
// Non quoted values
{ "09aAzZ", "attachment; filename=09aAzZ" },
{ "a.b", "attachment; filename=a.b" },
{ "#", "attachment; filename=#" },
{ "-", "attachment; filename=-" },
{ "_", "attachment; filename=_" },
{ "09aAzZ", "attachment; filename=09aAzZ; filename*=UTF-8''09aAzZ" },
{ "a.b", "attachment; filename=a.b; filename*=UTF-8''a.b" },
{ "#", "attachment; filename=#; filename*=UTF-8''#" },
{ "-", "attachment; filename=-; filename*=UTF-8''-" },
{ "_", "attachment; filename=_; filename*=UTF-8''_" },
{ "~", "attachment; filename=~; filename*=UTF-8''~" },
{ "$", "attachment; filename=$; filename*=UTF-8''$" },
{ "&", "attachment; filename=&; filename*=UTF-8''&" },
{ "+", "attachment; filename=+; filename*=UTF-8''+" },
{ "!", "attachment; filename=!; filename*=UTF-8''!" },
{ "#", "attachment; filename=#; filename*=UTF-8''#" },
{ "^", "attachment; filename=^; filename*=UTF-8''^" },
{ "`", "attachment; filename=`; filename*=UTF-8''`" },
{ "|", "attachment; filename=|; filename*=UTF-8''|" },
// Values that need to be quoted
{ ": :", "attachment; filename=\": :\"" },
{ "~", "attachment; filename=~" },
{ "$", "attachment; filename=$" },
{ "&", "attachment; filename=&" },
{ "+", "attachment; filename=+" },
{ "(", "attachment; filename=\"(\"" },
{ ")", "attachment; filename=\")\"" },
{ "<", "attachment; filename=\"<\"" },
{ ">", "attachment; filename=\">\"" },
{ "@", "attachment; filename=\"@\"" },
{ ",", "attachment; filename=\",\"" },
{ ";", "attachment; filename=\";\"" },
{ ":", "attachment; filename=\":\"" },
{ "/", "attachment; filename=\"/\"" },
{ "[", "attachment; filename=\"[\"" },
{ "]", "attachment; filename=\"]\"" },
{ "?", "attachment; filename=\"?\"" },
{ "=", "attachment; filename=\"=\"" },
{ "{", "attachment; filename=\"{\"" },
{ "}", "attachment; filename=\"}\"" },
{ " ", "attachment; filename=\" \"" },
{ "a\tb", "attachment; filename=\"a\tb\"" },
{ "a b", "attachment; filename=\"a b\"" },
{ ": :", "attachment; filename=\": :\"; filename*=UTF-8''%3A%20%3A" },
{ "(", "attachment; filename=\"(\"; filename*=UTF-8''%28" },
{ ")", "attachment; filename=\")\"; filename*=UTF-8''%29" },
{ "<", "attachment; filename=\"<\"; filename*=UTF-8''%3C" },
{ ">", "attachment; filename=\">\"; filename*=UTF-8''%3E" },
{ "@", "attachment; filename=\"@\"; filename*=UTF-8''%40" },
{ ",", "attachment; filename=\",\"; filename*=UTF-8''%2C" },
{ ";", "attachment; filename=\";\"; filename*=UTF-8''%3B" },
{ ":", "attachment; filename=\":\"; filename*=UTF-8''%3A" },
{ "/", "attachment; filename=\"/\"; filename*=UTF-8''%2F" },
{ "[", "attachment; filename=\"[\"; filename*=UTF-8''%5B" },
{ "]", "attachment; filename=\"]\"; filename*=UTF-8''%5D" },
{ "?", "attachment; filename=\"?\"; filename*=UTF-8''%3F" },
{ "=", "attachment; filename=\"=\"; filename*=UTF-8''%3D" },
{ "{", "attachment; filename=\"{\"; filename*=UTF-8''%7B" },
{ "}", "attachment; filename=\"}\"; filename*=UTF-8''%7D" },
{ " ", "attachment; filename=\" \"; filename*=UTF-8''%20" },
{ "a\tb", "attachment; filename=\"a\tb\"; filename*=UTF-8''a%09b" },
{ "a b", "attachment; filename=\"a b\"; filename*=UTF-8''a%20b" },
// Values that need to be escaped
{ "\"", "attachment; filename=\"\\\"\"" },
{ "\\", "attachment; filename=\"\\\\\"" },
{ "\"", "attachment; filename=\"\\\"\"; filename*=UTF-8''%22" },
{ "\\", "attachment; filename=\"\\\\\"; filename*=UTF-8''%5C" },
// Values that need to be specially encoded (Base64, see rfc2047)
{ "a\nb", "attachment; filename=\"=?utf-8?B?YQpi?=\"" },
{ "a\nb", "attachment; filename=\"a\nb\"; filename*=UTF-8''a%0Ab" },
// Values with non unicode characters
{ "résumé.txt", "attachment; filename*=UTF-8''r%C3%A9sum%C3%A9.txt" },
{ "Δ", "attachment; filename*=UTF-8''%CE%94" },
{ "Δ\t", "attachment; filename*=UTF-8''%CE%94%09" },
{ "ABCXYZabcxyz012789!@#$%^&*()-=_+.:~Δ", @"attachment; filename*=UTF-8''ABCXYZabcxyz012789!%40%23$%25%5E&%2A%28%29-%3D_+.:~%CE%94" },
{ "résumé.txt", "attachment; filename=r_sum_.txt; filename*=UTF-8''r%C3%A9sum%C3%A9.txt" },
{ "Δ", "attachment; filename=_; filename*=UTF-8''%CE%94" },
{ "Δ\t", "attachment; filename=\"_\t\"; filename*=UTF-8''%CE%94%09" },
{ "ABCXYZabcxyz012789!@#$%^&*()-=_+.:~Δ", @"attachment; filename=""ABCXYZabcxyz012789!@#$%^&*()-=_+.:~_""; filename*=UTF-8''ABCXYZabcxyz012789!%40#$%25^&%2A%28%29-%3D_+.%3A~%CE%94" },
};
}
}
@ -190,10 +185,10 @@ namespace Microsoft.AspNet.Mvc
continue;
}
data.Add(char.ConvertFromUtf32(i), "attachment; filename=\"" + char.ConvertFromUtf32(i) + "\"");
data.Add(char.ConvertFromUtf32(i), "attachment; filename=\"" + char.ConvertFromUtf32(i) + "\"; filename*=UTF-8''%" + i.ToString("X2"));
}
data.Add(char.ConvertFromUtf32(127), "attachment; filename=\"" + char.ConvertFromUtf32(127) + "\"");
data.Add(char.ConvertFromUtf32(127), "attachment; filename=\"" + char.ConvertFromUtf32(127) + "\"; filename*=UTF-8''%7F");
return data;
}
@ -205,7 +200,9 @@ namespace Microsoft.AspNet.Mvc
public void GetHeaderValue_Produces_Correct_ContentDisposition(string input, string expectedOutput)
{
// Arrange & Act
var actual = FileResult.ContentDispositionUtil.GetHeaderValue(input);
var cd = new ContentDispositionHeaderValue("attachment");
cd.SetHttpFileName(input);
var actual = cd.ToString();
// Assert
Assert.Equal(expectedOutput, actual);

View File

@ -8,11 +8,12 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
using Microsoft.AspNet.PipelineCore;
using Microsoft.AspNet.Routing;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.DependencyInjection.Fallback;
using Microsoft.Framework.OptionsModel;
using Microsoft.Net.Http.Headers;
using Moq;
using Xunit;
@ -32,25 +33,25 @@ namespace Microsoft.AspNet.Mvc.Core.Test.ActionResults
};
// Empty accept header, should select based on contentTypes.
yield return new object[] { contentTypes, "", "application/json;charset=utf-8" };
yield return new object[] { contentTypes, "", "application/json; charset=utf-8" };
// null accept header, should select based on contentTypes.
yield return new object[] { contentTypes, null, "application/json;charset=utf-8" };
yield return new object[] { contentTypes, null, "application/json; charset=utf-8" };
// No accept Header match with given contentype collection.
// Should select based on if any formatter supported any content type.
yield return new object[] { contentTypes, "text/custom", "application/json;charset=utf-8" };
yield return new object[] { contentTypes, "text/custom", "application/json; charset=utf-8" };
// Accept Header matches but no formatter supports the accept header.
// Should select based on if any formatter supported any user provided content type.
yield return new object[] { contentTypes, "text/xml", "application/json;charset=utf-8" };
yield return new object[] { contentTypes, "text/xml", "application/json; charset=utf-8" };
// Filtets out Accept headers with 0 quality and selects the one with highest quality.
yield return new object[]
{
contentTypes,
"text/plain;q=0.3, text/json;q=0, text/cusotm;q=0.0, application/json;q=0.4",
"application/json;charset=utf-8"
"application/json; charset=utf-8"
};
}
}
@ -107,12 +108,13 @@ namespace Microsoft.AspNet.Mvc.Core.Test.ActionResults
public async Task ObjectResult_WithSingleContentType_TheGivenContentTypeIsSelected()
{
// Arrange
var expectedContentType = "application/json;charset=utf-8";
var expectedContentType = "application/json; charset=utf-8";
// non string value.
var input = 123;
var httpResponse = GetMockHttpResponse();
var actionContext = CreateMockActionContext(httpResponse.Object);
var httpResponse = new DefaultHttpContext().Response;
httpResponse.Body = new MemoryStream();
var actionContext = CreateMockActionContext(httpResponse);
// Set the content type property explicitly to a single value.
var result = new ObjectResult(input);
@ -123,7 +125,7 @@ namespace Microsoft.AspNet.Mvc.Core.Test.ActionResults
await result.ExecuteResultAsync(actionContext);
// Assert
httpResponse.VerifySet(r => r.ContentType = expectedContentType);
Assert.Equal(expectedContentType, httpResponse.ContentType);
}
[Fact]
@ -131,7 +133,7 @@ namespace Microsoft.AspNet.Mvc.Core.Test.ActionResults
{
// Arrange
var contentType = "application/json;charset=utf-8";
var expectedContentType = "text/plain;charset=utf-8";
var expectedContentType = "text/plain; charset=utf-8";
// string value.
var input = "1234";
@ -154,7 +156,7 @@ namespace Microsoft.AspNet.Mvc.Core.Test.ActionResults
public async Task ObjectResult_MultipleContentTypes_PicksFirstFormatterWhichSupportsAnyOfTheContentTypes()
{
// Arrange
var expectedContentType = "application/json;charset=utf-8";
var expectedContentType = "application/json; charset=utf-8";
var input = "testInput";
var httpResponse = GetMockHttpResponse();
var actionContext = CreateMockActionContext(httpResponse.Object, requestAcceptHeader: null);
@ -217,7 +219,7 @@ namespace Microsoft.AspNet.Mvc.Core.Test.ActionResults
public async Task ObjectResult_NoContentTypeSetWithAcceptHeaders_PicksFormatterOnAcceptHeaders()
{
// Arrange
var expectedContentType = "application/json;charset=utf-8";
var expectedContentType = "application/json; charset=utf-8";
var input = "testInput";
var stream = new MemoryStream();
@ -248,7 +250,7 @@ namespace Microsoft.AspNet.Mvc.Core.Test.ActionResults
{
// Arrange
var stream = new MemoryStream();
var expectedContentType = "application/json;charset=utf-8";
var expectedContentType = "application/json; charset=utf-8";
var httpResponse = new Mock<HttpResponse>();
httpResponse.SetupProperty<string>(o => o.ContentType);
httpResponse.SetupGet(r => r.Body).Returns(stream);
@ -287,10 +289,7 @@ namespace Microsoft.AspNet.Mvc.Core.Test.ActionResults
// For each additional accept header, it is called once.
// Arrange
var acceptHeaderCollection = string.IsNullOrEmpty(acceptHeader) ?
null :
acceptHeader?.Split(',')
.Select(header => MediaTypeWithQualityHeaderValue.Parse(header))
.ToArray();
null : MediaTypeHeaderValue.ParseList(new[] { acceptHeader }).ToArray();
var stream = new MemoryStream();
var httpResponse = new Mock<HttpResponse>();
httpResponse.SetupProperty<string>(o => o.ContentType);
@ -349,7 +348,7 @@ namespace Microsoft.AspNet.Mvc.Core.Test.ActionResults
{
// Arrange
var stream = new MemoryStream();
var expectedContentType = "application/json;charset=utf-8";
var expectedContentType = "application/json; charset=utf-8";
var httpResponse = new Mock<HttpResponse>();
httpResponse.SetupProperty<string>(o => o.ContentType);
httpResponse.SetupGet(r => r.Body).Returns(stream);
@ -406,7 +405,7 @@ namespace Microsoft.AspNet.Mvc.Core.Test.ActionResults
public async Task ObjectResult_Execute_CallsContentResult_SetsContent()
{
// Arrange
var expectedContentType = "text/plain;charset=utf-8";
var expectedContentType = "text/plain; charset=utf-8";
var input = "testInput";
var stream = new MemoryStream();
@ -433,7 +432,7 @@ namespace Microsoft.AspNet.Mvc.Core.Test.ActionResults
public async Task ObjectResult_Execute_CallsJsonResult_SetsContent()
{
// Arrange
var expectedContentType = "application/json;charset=utf-8";
var expectedContentType = "application/json; charset=utf-8";
var nonStringValue = new { x1 = 10, y1 = "Hello" };
var httpResponse = Mock.Of<HttpResponse>();
httpResponse.Body = new MemoryStream();
@ -444,8 +443,8 @@ namespace Microsoft.AspNet.Mvc.Core.Test.ActionResults
tempHttpResponse.SetupGet(o => o.Body).Returns(tempStream);
tempHttpResponse.SetupProperty<string>(o => o.ContentType);
tempHttpContext.SetupGet(o => o.Request).Returns(new DefaultHttpContext().Request);
tempHttpContext.SetupGet(o => o.Response).Returns(tempHttpResponse.Object);
tempHttpContext.SetupGet(o => o.Request.AcceptCharset).Returns(string.Empty);
var tempActionContext = new ActionContext(tempHttpContext.Object,
new RouteData(),
new ActionDescriptor());
@ -482,13 +481,13 @@ namespace Microsoft.AspNet.Mvc.Core.Test.ActionResults
var content = "{name: 'Person Name', Age: 'not-an-age'}";
var contentBytes = Encoding.UTF8.GetBytes(content);
var request = new Mock<HttpRequest>();
request.SetupGet(r => r.AcceptCharset).Returns(requestAcceptCharsetHeader);
request.SetupGet(r => r.Accept).Returns(requestAcceptHeader);
request.SetupGet(r => r.ContentType).Returns(requestContentType);
request.SetupGet(f => f.Body).Returns(new MemoryStream(contentBytes));
var request = new DefaultHttpContext().Request;
request.Headers["Accept-Charset"] = requestAcceptCharsetHeader;
request.Headers["Accept"] = requestAcceptHeader;
request.ContentType = requestContentType;
request.Body = new MemoryStream(contentBytes);
httpContext.Setup(o => o.Request).Returns(request.Object);
httpContext.Setup(o => o.Request).Returns(request);
httpContext.Setup(o => o.RequestServices).Returns(GetServiceProvider());
httpContext.Setup(o => o.RequestServices.GetService(typeof(IOutputFormattersProvider)))
.Returns(new TestOutputFormatterProvider());

View File

@ -9,6 +9,7 @@ using System.Reflection;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.PipelineCore;
using Microsoft.AspNet.Routing;
using Microsoft.AspNet.Testing;
using Microsoft.Framework.DependencyInjection;
@ -1941,7 +1942,8 @@ namespace Microsoft.AspNet.Mvc
}
var httpContext = new Mock<HttpContext>(MockBehavior.Loose);
var httpResponse = new Mock<HttpResponse>(MockBehavior.Loose);
var httpRequest = new DefaultHttpContext().Request;
var httpResponse = new DefaultHttpContext().Response;
var mockFormattersProvider = new Mock<IOutputFormattersProvider>();
mockFormattersProvider.SetupGet(o => o.OutputFormatters)
.Returns(
@ -1949,12 +1951,11 @@ namespace Microsoft.AspNet.Mvc
{
new JsonOutputFormatter()
});
httpContext.SetupGet(o => o.Request.Accept)
.Returns("");
httpContext.SetupGet(c => c.Response).Returns(httpResponse.Object);
httpContext.SetupGet(c => c.Request).Returns(httpRequest);
httpContext.SetupGet(c => c.Response).Returns(httpResponse);
httpContext.Setup(o => o.RequestServices.GetService(typeof(IOutputFormattersProvider)))
.Returns(mockFormattersProvider.Object);
httpResponse.SetupGet(r => r.Body).Returns(new MemoryStream());
httpResponse.Body = new MemoryStream();
var actionContext = new ActionContext(
httpContext: httpContext.Object,

View File

@ -5,11 +5,11 @@ using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.Routing;
using Microsoft.AspNet.Routing;
using Microsoft.AspNet.Routing.Constraints;
using Microsoft.Net.Http.Headers;
using Moq;
using Xunit;
@ -522,10 +522,10 @@ namespace Microsoft.AspNet.Mvc.Description
Assert.Equal(4, description.SupportedResponseFormats.Count);
var formats = description.SupportedResponseFormats;
Assert.Single(formats, f => f.MediaType.RawValue == "text/json");
Assert.Single(formats, f => f.MediaType.RawValue == "application/json");
Assert.Single(formats, f => f.MediaType.RawValue == "text/xml");
Assert.Single(formats, f => f.MediaType.RawValue == "application/xml");
Assert.Single(formats, f => f.MediaType.ToString() == "text/json");
Assert.Single(formats, f => f.MediaType.ToString() == "application/json");
Assert.Single(formats, f => f.MediaType.ToString() == "text/xml");
Assert.Single(formats, f => f.MediaType.ToString() == "application/xml");
}
[Fact]
@ -545,8 +545,8 @@ namespace Microsoft.AspNet.Mvc.Description
Assert.Equal(2, description.SupportedResponseFormats.Count);
var formats = description.SupportedResponseFormats;
Assert.Single(formats, f => f.MediaType.RawValue == "text/json");
Assert.Single(formats, f => f.MediaType.RawValue == "text/xml");
Assert.Single(formats, f => f.MediaType.ToString() == "text/json");
Assert.Single(formats, f => f.MediaType.ToString() == "text/xml");
}
[Fact]
@ -580,7 +580,7 @@ namespace Microsoft.AspNet.Mvc.Description
Assert.NotNull(description.ResponseModelMetadata);
var formats = description.SupportedResponseFormats;
Assert.Single(formats, f => f.MediaType.RawValue == "text/json");
Assert.Single(formats, f => f.MediaType.ToString() == "text/json");
Assert.Same(formatters[0], formats[0].Formatter);
}

View File

@ -3,9 +3,9 @@
using System;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
using Microsoft.AspNet.PipelineCore;
using Microsoft.AspNet.Routing;
using Microsoft.Net.Http.Headers;
using Xunit;
namespace Microsoft.AspNet.Mvc.Test
@ -40,22 +40,23 @@ namespace Microsoft.AspNet.Mvc.Test
public void ProducesAttribute_InvalidContentType_Throws(string content)
{
// Act & Assert
var ex = Assert.Throws<ArgumentException>(
var ex = Assert.Throws<FormatException>(
() => new ProducesAttribute(content));
Assert.Equal("Invalid Argument. Content type '" + content + "' could not be parsed.",
Assert.Equal("Invalid value '" + (content ?? "<null>") + "'.",
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.SubType, actualMediaType.SubType);
Assert.Equal(expectedMediaType.Charset, actualMediaType.Charset);
Assert.Equal(expectedMediaType.MediaTypeRange, actualMediaType.MediaTypeRange);
Assert.Equal(expectedMediaType.MatchesAllTypes, actualMediaType.MatchesAllTypes);
Assert.Equal(expectedMediaType.MatchesAllSubTypes, actualMediaType.MatchesAllSubTypes);
Assert.Equal(expectedMediaType.Parameters.Count, actualMediaType.Parameters.Count);
foreach (var item in expectedMediaType.Parameters)
{
Assert.Equal(item.Value, actualMediaType.Parameters[item.Key]);
Assert.Equal(item.Value, NameValueHeaderValue.Find(actualMediaType.Parameters, item.Name).Value);
}
}

View File

@ -57,7 +57,7 @@ namespace Microsoft.AspNet.Mvc
var mediaType = formatter.SupportedMediaTypes[0];
// Assert
Assert.Equal("application/json", mediaType.RawValue);
Assert.Equal("application/json", mediaType.ToString());
}
public static IEnumerable<object[]> JsonFormatterReadSimpleTypesData

View File

@ -6,7 +6,8 @@ using System.IO;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
using Microsoft.AspNet.PipelineCore.Collections;
using Microsoft.Net.Http.Headers;
using Moq;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
@ -103,10 +104,10 @@ namespace Microsoft.AspNet.Mvc.Core.Test.Formatters
private static ActionContext GetActionContext(MediaTypeHeaderValue contentType)
{
var request = new Mock<HttpRequest>();
var headers = new Mock<IHeaderDictionary>();
request.Setup(r => r.ContentType).Returns(contentType.RawValue);
request.SetupGet(r => r.Headers).Returns(headers.Object);
request.SetupGet(f => f.AcceptCharset).Returns(contentType.Charset);
var headers = new HeaderDictionary();
request.Setup(r => r.ContentType).Returns(contentType.ToString());
request.SetupGet(r => r.Headers).Returns(headers);
headers[HeaderNames.AcceptCharset] = contentType.Charset;
var response = new Mock<HttpResponse>();
response.SetupGet(f => f.Body).Returns(new MemoryStream());
var httpContext = new Mock<HttpContext>();

View File

@ -4,9 +4,9 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
using Microsoft.AspNet.PipelineCore;
using Microsoft.AspNet.Routing;
using Microsoft.Net.Http.Headers;
using Xunit;
namespace Microsoft.AspNet.Mvc.Test

View File

@ -6,8 +6,9 @@ using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
using Microsoft.AspNet.PipelineCore;
using Microsoft.AspNet.Routing;
using Microsoft.Net.Http.Headers;
using Moq;
using Xunit;
@ -48,10 +49,10 @@ namespace Microsoft.AspNet.Mvc.Test
{
// Arrange
var mockHttpContext = new Mock<HttpContext>();
mockHttpContext.SetupGet(o => o.Request.AcceptCharset)
.Returns(acceptCharsetHeaders);
mockHttpContext.SetupGet(o => o.Request.ContentType)
.Returns("application/acceptCharset;charset=" + requestEncoding);
var httpRequest = new DefaultHttpContext().Request;
httpRequest.Headers["Accept-Charset"] = acceptCharsetHeaders;
httpRequest.ContentType = "application/acceptCharset;charset=" + requestEncoding;
mockHttpContext.SetupGet(o => o.Request).Returns(httpRequest);
var actionContext = new ActionContext(mockHttpContext.Object, new RouteData(), new ActionDescriptor());
var formatter = new TestOutputFormatter();
foreach (string supportedEncoding in supportedEncodings)
@ -81,8 +82,8 @@ namespace Microsoft.AspNet.Mvc.Test
var testContentType = MediaTypeHeaderValue.Parse("text/invalid");
var formatterContext = new OutputFormatterContext();
var mockHttpContext = new Mock<HttpContext>();
mockHttpContext.SetupGet(o => o.Request.AcceptCharset)
.Returns(string.Empty);
var httpRequest = new DefaultHttpContext().Request;
mockHttpContext.SetupGet(o => o.Request).Returns(httpRequest);
var actionContext = new ActionContext(mockHttpContext.Object, new RouteData(), new ActionDescriptor());
formatterContext.ActionContext = actionContext;
@ -103,8 +104,8 @@ namespace Microsoft.AspNet.Mvc.Test
var testContentType = MediaTypeHeaderValue.Parse("application/doesNotSetContext");
var formatterContext = new OutputFormatterContext();
var mockHttpContext = new Mock<HttpContext>();
mockHttpContext.SetupGet(o => o.Request.AcceptCharset)
.Returns(string.Empty);
var httpRequest = new DefaultHttpContext().Request;
mockHttpContext.SetupGet(o => o.Request).Returns(httpRequest);
mockHttpContext.SetupProperty(o => o.Response.ContentType);
var actionContext = new ActionContext(mockHttpContext.Object, new RouteData(), new ActionDescriptor());
formatterContext.ActionContext = actionContext;
@ -115,8 +116,8 @@ namespace Microsoft.AspNet.Mvc.Test
// Assert
Assert.Equal(Encodings.UTF16EncodingLittleEndian.WebName, formatterContext.SelectedEncoding.WebName);
Assert.Equal(Encodings.UTF16EncodingLittleEndian, formatterContext.SelectedEncoding);
Assert.Equal("application/doesNotSetContext;charset=" + Encodings.UTF16EncodingLittleEndian.WebName,
formatterContext.SelectedContentType.RawValue);
Assert.Equal("application/doesNotSetContext; charset=" + Encodings.UTF16EncodingLittleEndian.WebName,
formatterContext.SelectedContentType.ToString());
}
[Fact]
@ -131,7 +132,7 @@ namespace Microsoft.AspNet.Mvc.Test
// Assert
Assert.True(result);
Assert.Equal(formatter.SupportedMediaTypes[0].RawValue, context.SelectedContentType.RawValue);
Assert.Equal(formatter.SupportedMediaTypes[0].ToString(), context.SelectedContentType.ToString());
}
[Fact]
@ -190,8 +191,8 @@ namespace Microsoft.AspNet.Mvc.Test
// Assert
Assert.Equal(2, contentTypes.Count);
Assert.Single(contentTypes, ct => ct.RawValue == "application/json");
Assert.Single(contentTypes, ct => ct.RawValue == "application/xml");
Assert.Single(contentTypes, ct => ct.ToString() == "application/json");
Assert.Single(contentTypes, ct => ct.ToString() == "application/xml");
}
[Fact]
@ -212,7 +213,7 @@ namespace Microsoft.AspNet.Mvc.Test
// Assert
var contentType = Assert.Single(contentTypes);
Assert.Equal("application/json", contentType.RawValue);
Assert.Equal("application/json", contentType.ToString());
}
[Fact]

View File

@ -80,10 +80,10 @@ namespace Microsoft.AspNet.Mvc
// Assert
Assert.True(formatter.SupportedMediaTypes
.Select(content => content.RawValue)
.Select(content => content.ToString())
.Contains("application/xml"));
Assert.True(formatter.SupportedMediaTypes
.Select(content => content.RawValue)
.Select(content => content.ToString())
.Contains("text/xml"));
}

View File

@ -8,7 +8,8 @@ using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
using Microsoft.AspNet.PipelineCore.Collections;
using Microsoft.Net.Http.Headers;
using Moq;
using Xunit;
@ -297,7 +298,7 @@ namespace Microsoft.AspNet.Mvc.Core
// Assert
if (expectedOutput != null)
{
Assert.Equal(expectedOutput, Assert.Single(result).RawValue);
Assert.Equal(expectedOutput, Assert.Single(result).ToString());
}
else
{
@ -319,10 +320,10 @@ namespace Microsoft.AspNet.Mvc.Core
private static ActionContext GetActionContext(string contentType)
{
var request = new Mock<HttpRequest>();
var headers = new Mock<IHeaderDictionary>();
var headers = new HeaderDictionary(new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase));
headers["Accept-Charset"] = MediaTypeHeaderValue.Parse(contentType).Charset;
request.Setup(r => r.ContentType).Returns(contentType);
request.SetupGet(r => r.Headers).Returns(headers.Object);
request.SetupGet(f => f.AcceptCharset).Returns(contentType.Split('=')[1]);
request.SetupGet(r => r.Headers).Returns(headers);
var response = new Mock<HttpResponse>();
response.SetupGet(f => f.Body).Returns(new MemoryStream());
var httpContext = new Mock<HttpContext>();

View File

@ -71,10 +71,10 @@ namespace Microsoft.AspNet.Mvc
// Assert
Assert.True(formatter.SupportedMediaTypes
.Select(content => content.RawValue)
.Select(content => content.ToString())
.Contains("application/xml"));
Assert.True(formatter.SupportedMediaTypes
.Select(content => content.RawValue)
.Select(content => content.ToString())
.Contains("text/xml"));
}

View File

@ -7,7 +7,8 @@ using System.IO;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
using Microsoft.AspNet.PipelineCore.Collections;
using Microsoft.Net.Http.Headers;
using Moq;
using Xunit;
@ -281,7 +282,7 @@ namespace Microsoft.AspNet.Mvc.Core
// Assert
if (expectedOutput != null)
{
Assert.Equal(expectedOutput, Assert.Single(result).RawValue);
Assert.Equal(expectedOutput, Assert.Single(result).ToString());
}
else
{
@ -303,10 +304,10 @@ namespace Microsoft.AspNet.Mvc.Core
private static ActionContext GetActionContext(string contentType)
{
var request = new Mock<HttpRequest>();
var headers = new Mock<IHeaderDictionary>();
var headers = new HeaderDictionary(new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase));
headers["Accept-Charset"] = MediaTypeHeaderValue.Parse(contentType).Charset;
request.Setup(r => r.ContentType).Returns(contentType);
request.SetupGet(r => r.Headers).Returns(headers.Object);
request.SetupGet(f => f.AcceptCharset).Returns(contentType.Split('=')[1]);
request.SetupGet(r => r.Headers).Returns(headers);
var response = new Mock<HttpResponse>();
response.SetupGet(f => f.Body).Returns(new MemoryStream());
var httpContext = new Mock<HttpContext>();

View File

@ -8,9 +8,9 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
using Microsoft.AspNet.PipelineCore;
using Microsoft.AspNet.Routing;
using Microsoft.Net.Http.Headers;
using Moq;
using Xunit;
@ -44,7 +44,7 @@ namespace Microsoft.AspNet.Mvc
// Assert
Assert.Equal(expected, written);
Assert.Equal("application/json;charset=utf-8", context.Response.ContentType);
Assert.Equal("application/json; charset=utf-8", context.Response.ContentType);
}
[Fact]
@ -70,7 +70,7 @@ namespace Microsoft.AspNet.Mvc
// Assert
Assert.Equal(expected, written);
Assert.Equal("application/json;charset=utf-8", context.Response.ContentType);
Assert.Equal("application/json; charset=utf-8", context.Response.ContentType);
}
[Fact]
@ -86,7 +86,7 @@ namespace Microsoft.AspNet.Mvc
};
var context = GetHttpContext(optionsFormatters);
context.Request.Accept = "text/json";
context.Request.Headers["Accept"] = "text/json";
var actionContext = new ActionContext(context, new RouteData(), new ActionDescriptor());
@ -98,7 +98,7 @@ namespace Microsoft.AspNet.Mvc
// Assert
Assert.Equal(expected, written);
Assert.Equal("text/json;charset=utf-8", context.Response.ContentType);
Assert.Equal("text/json; charset=utf-8", context.Response.ContentType);
}
[Fact]
@ -124,7 +124,7 @@ namespace Microsoft.AspNet.Mvc
// Assert
Assert.Equal(expected, written);
Assert.Equal("application/json;charset=utf-8", context.Response.ContentType);
Assert.Equal("application/json; charset=utf-8", context.Response.ContentType);
}
[Fact]
@ -148,7 +148,7 @@ namespace Microsoft.AspNet.Mvc
// Assert
Assert.Equal(expected, written);
Assert.Equal("application/hal+json;charset=utf-8", context.Response.ContentType);
Assert.Equal("application/hal+json; charset=utf-8", context.Response.ContentType);
}
// If no formatter in options can match the given content-types, then use the one registered
@ -170,7 +170,7 @@ namespace Microsoft.AspNet.Mvc
// Assert
Assert.Equal(expected, written);
Assert.Equal("application/json;charset=utf-8", context.Response.ContentType);
Assert.Equal("application/json; charset=utf-8", context.Response.ContentType);
}
private HttpContext GetHttpContext(

View File

@ -1,81 +0,0 @@
// 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.Linq;
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
using Xunit;
namespace Microsoft.AspNet.Mvc.Core.Test
{
public class MediaTypeWithQualityHeaderValueTests
{
public static IEnumerable<object[]> SortValues
{
get
{
yield return new object[] {
new string[]
{
"application/*",
"text/plain",
"text/plain;q=1.0",
"text/plain",
"text/plain;q=0",
"*/*;q=0.8",
"*/*;q=1",
"text/*;q=1",
"text/plain;q=0.8",
"text/*;q=0.8",
"text/*;q=0.6",
"text/*;q=1.0",
"*/*;q=0.4",
"text/plain;q=0.6",
"text/xml",
},
new string[]
{
"text/plain",
"text/plain;q=1.0",
"text/plain",
"text/xml",
"application/*",
"text/*;q=1",
"text/*;q=1.0",
"*/*;q=1",
"text/plain;q=0.8",
"text/*;q=0.8",
"*/*;q=0.8",
"text/plain;q=0.6",
"text/*;q=0.6",
"*/*;q=0.4",
"text/plain;q=0",
}
};
}
}
[Theory]
[MemberData(nameof(SortValues))]
public void SortMediaTypeWithQualityHeaderValuesByQFactor_SortsCorrectly(IEnumerable<string> unsorted, IEnumerable<string> expectedSorted)
{
// Arrange
var unsortedValues =
new List<MediaTypeWithQualityHeaderValue>(
unsorted.Select(u => MediaTypeWithQualityHeaderValue.Parse(u)));
var expectedSortedValues =
new List<MediaTypeWithQualityHeaderValue>(
expectedSorted.Select(u => MediaTypeWithQualityHeaderValue.Parse(u)));
// Act
var actualSorted = unsortedValues.OrderByDescending(m => m, MediaTypeWithQualityHeaderValueComparer.QualityComparer).ToArray();
// Assert
for (int i = 0; i < expectedSortedValues.Count; i++)
{
Assert.True(MediaTypeWithQualityHeaderValueComparer.QualityComparer.Compare(expectedSortedValues[i], actualSorted[i]) == 0);
}
}
}
}

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
@ -14,4 +14,9 @@
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>
<ProjectExtensions>
<VisualStudio>
<UserProperties project_1json__JSONSchema="http://www.asp.net/media/4878834/project.json" />
</VisualStudio>
</ProjectExtensions>
</Project>

View File

@ -4,7 +4,7 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
using Microsoft.Net.Http.Headers;
using Microsoft.AspNet.Mvc.OptionDescriptors;
using Microsoft.AspNet.Testing;
using Xunit;

View File

@ -105,8 +105,8 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
}
[Theory]
[InlineData("ContactInfoUsingV3Format", "text/vcard; charset=utf-8; version=v3.0", "BEGIN:VCARD#FN:John Williams#END:VCARD#")]
[InlineData("ContactInfoUsingV4Format", "text/vcard; charset=utf-8; version=v4.0", "BEGIN:VCARD#FN:John Williams#GENDER:M#END:VCARD#")]
[InlineData("ContactInfoUsingV3Format", "text/vcard; version=v3.0; charset=utf-8", "BEGIN:VCARD#FN:John Williams#END:VCARD#")]
[InlineData("ContactInfoUsingV4Format", "text/vcard; version=v4.0; charset=utf-8", "BEGIN:VCARD#FN:John Williams#GENDER:M#END:VCARD#")]
public async Task ProducesAttribute_WithMediaTypeHavingParameters_IsCaseInsensitiveMatch(
string action,
string expectedMediaType,

View File

@ -58,7 +58,7 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
var contentDisposition = response.Content.Headers.ContentDisposition.ToString();
Assert.NotNull(contentDisposition);
Assert.Equal("attachment; filename=downloadName.txt", contentDisposition);
Assert.Equal("attachment; filename=downloadName.txt; filename*=UTF-8''downloadName.txt", contentDisposition);
}
[Fact]
@ -104,7 +104,7 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
var contentDisposition = response.Content.Headers.ContentDisposition.ToString();
Assert.NotNull(contentDisposition);
Assert.Equal("attachment; filename=downloadName.txt", contentDisposition);
Assert.Equal("attachment; filename=downloadName.txt; filename*=UTF-8''downloadName.txt", contentDisposition);
}
[Fact]
@ -150,7 +150,7 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
var contentDisposition = response.Content.Headers.ContentDisposition.ToString();
Assert.NotNull(contentDisposition);
Assert.Equal("attachment; filename=downloadName.txt", contentDisposition);
Assert.Equal("attachment; filename=downloadName.txt; filename*=UTF-8''downloadName.txt", contentDisposition);
}
}
}

View File

@ -1,90 +0,0 @@
// 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 Xunit;
namespace Microsoft.AspNet.Mvc.HeaderValueAbstractions
{
public class HeaderParsingHelpersTests
{
//Accept Headers
[Fact]
public void GetAcceptHeaders_ReturnsParsedHeaders()
{
// Arrange & Act
var headers = HeaderParsingHelpers.GetAcceptHeaders("application/xml;q=0.4, application/xhtml;q=0.9");
// Assert
Assert.Equal(2, headers.Count);
Assert.Equal("application", headers[0].MediaType);
Assert.Equal("xml", headers[0].MediaSubType);
Assert.Equal(0.4, headers[0].Quality);
Assert.Equal("application", headers[1].MediaType);
Assert.Equal("xhtml", headers[1].MediaSubType);
Assert.Equal(0.9, headers[1].Quality);
}
public static IEnumerable<object[]> CasesWhereGetAcceptHeadersReturnsNull
{
get
{
yield return new object[] { "" };
yield return new object[] { "application/xml;q=0.4, application/xhtml;q=0,9" };
yield return new object[] { "application/xml;q=0.4, application/xhtml;q=-0.4" };
yield return new object[] { "application/xml;q=0 4" };
yield return new object[] { "application/xml;q=0*4" };
yield return new object[] { "application/xml;q=1^4" };
}
}
[Theory]
[MemberData(nameof(CasesWhereGetAcceptHeadersReturnsNull))]
public void GetAcceptHeaders_ReturnsNull(string acceptHeader)
{
// Arrange & Act
var headers = HeaderParsingHelpers.GetAcceptHeaders(acceptHeader);
// Assert
Assert.Null(headers);
}
// Charset Headers
[Fact]
public void GetAcceptCharsetHeaders_ReturnsParsedHeaders()
{
// Arrange & Act
var headers = HeaderParsingHelpers.GetAcceptCharsetHeaders("utf-8;q=0.7,gzip;q=0.3");
// Assert
Assert.Equal(2, headers.Count);
Assert.Equal("utf-8", headers[0].Value);
Assert.Equal(0.7, headers[0].Quality);
Assert.Equal("gzip", headers[1].Value);
Assert.Equal(0.3, headers[1].Quality);
}
public static IEnumerable<object[]> CasesWhereGetCharsetHeadersReturnsNull
{
get
{
yield return new object[] { "" };
yield return new object[] { "utf-8;q=0,7,gzip;q=-1" };
yield return new object[] { "utf-8;q=0*7,gzip;q=1.0" };
yield return new object[] { "utf-8;q=0 7" };
yield return new object[] { "utf-8;q=0^7" };
}
}
[Theory]
[MemberData(nameof(CasesWhereGetCharsetHeadersReturnsNull))]
public void GetAcceptCharsetHeaders_ReturnsNull_IfAcceptHeaderIsEmpty(string charsetHeader)
{
// Arrange & Act
var headers = HeaderParsingHelpers.GetAcceptCharsetHeaders(charsetHeader);
// Assert
Assert.Null(headers);
}
}
}

View File

@ -1,170 +0,0 @@
// 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 Xunit;
namespace Microsoft.AspNet.Mvc.HeaderValueAbstractions
{
public class MediaTypeHeaderValueParsingTests
{
public static IEnumerable<object[]> GetValidMediaTypeWithQualityHeaderValues
{
get
{
yield return new object[]
{
"*",
"*",
null,
MediaTypeHeaderValueRange.AllMediaRange,
new Dictionary<string, string>(),
HttpHeaderUtilitites.Match,
"*/*"
};
yield return new object[]
{
"text",
"*",
"utf-8",
MediaTypeHeaderValueRange.SubtypeMediaRange,
new Dictionary<string, string>() { { "charset", "utf-8" }, { "foo", "bar" } },
HttpHeaderUtilitites.Match,
"text/*;charset=utf-8;foo=bar",
};
yield return new object[]
{
"text",
"plain",
"utf-8",
MediaTypeHeaderValueRange.None,
new Dictionary<string, string>() { { "charset", "utf-8" }, { "foo", "bar" }, { "q", "0.0" } },
HttpHeaderUtilitites.NoMatch,
"text/plain;charset=utf-8;foo=bar;q=0.0",
};
}
}
[Theory]
[MemberData(nameof(GetValidMediaTypeWithQualityHeaderValues))]
public void MediaTypeWithQualityHeaderValue_ParseSuccessfully(string mediaType,
string mediaSubType,
string charset,
MediaTypeHeaderValueRange range,
IDictionary<string, string> parameters,
double quality,
string rawValue)
{
// Arrange
var parsedValue = MediaTypeWithQualityHeaderValue.Parse(rawValue);
// Act and Assert
Assert.Equal(rawValue, parsedValue.RawValue);
Assert.Equal(mediaType, parsedValue.MediaType);
Assert.Equal(mediaSubType, parsedValue.MediaSubType);
Assert.Equal(charset, parsedValue.Charset);
Assert.Equal(range, parsedValue.MediaTypeRange);
Assert.Equal(quality, parsedValue.Quality);
ValidateParametes(parameters, parsedValue.Parameters);
}
[Theory]
[InlineData(false, "text", "plain", null, "text /plain;q=1,9")]
[InlineData(true, "text", "plain", 0.9, "text/plain;q=0.9")]
public void MediaTypeWithQualityHeaderValue_TryParse_ReturnsApproperiateResults(
bool result,
string mediaType,
string mediaSubType,
double quality,
string rawValue)
{
// Arrange
MediaTypeWithQualityHeaderValue parsedValue;
var isValid = MediaTypeWithQualityHeaderValue.TryParse(rawValue, out parsedValue);
// Act and Assert
Assert.Equal(result, isValid);
if(result)
{
Assert.Equal(rawValue, parsedValue.RawValue);
Assert.Equal(mediaType, parsedValue.MediaType);
Assert.Equal(mediaSubType, parsedValue.MediaSubType);
Assert.Equal(quality, parsedValue.Quality);
}
}
[Theory]
[InlineData("*/*;", "*/*", true)]
[InlineData("text/*;", "text/*", true)]
[InlineData("text/plain;", "text/plain", true)]
[InlineData("*/*;", "*/*;charset=utf-8;", true)]
[InlineData("text/*;", "*/*;charset=utf-8;", true)]
[InlineData("text/plain;", "*/*;charset=utf-8;", true)]
[InlineData("text/plain;", "text/*;charset=utf-8;", true)]
[InlineData("text/plain;", "text/plain;charset=utf-8;", true)]
[InlineData("text/plain;version=v1", "text/plain;version=", false)]
[InlineData("text/plain;version=v1", "Text/plain;Version=v1", true)]
[InlineData("text/plain;version=v1", "tExT/plain;version=V1", true)]
[InlineData("text/plain;version=v1", "TEXT/PLAIN;VERSION=V1", true)]
[InlineData("text/plain;charset=utf-8;foo=bar;q=0.0", "text/plain;charset=utf-8;foo=bar;q=0.0", true)]
[InlineData("text/plain;charset=utf-8;foo=bar;q=0.0", "text/plain;foo=bar;q=0.0;charset=utf-8", true)] // different order of parameters
[InlineData("text/plain;charset=utf-8;foo=bar;q=0.0", "text/*;charset=utf-8;foo=bar;q=0.0", true)]
[InlineData("text/plain;charset=utf-8;foo=bar;q=0.0", "*/*;charset=utf-8;foo=bar;q=0.0", true)]
[InlineData("*/*;", "text/plain;charset=utf-8;foo=bar;q=0.0", false)]
[InlineData("text/*;", "text/plain;charset=utf-8;foo=bar;q=0.0", false)]
[InlineData("text/plain;missingparam=4;", "text/plain;charset=utf-8;foo=bar;q=0.0", false)]
[InlineData("text/plain;missingparam=4;", "text/*;charset=utf-8;foo=bar;q=0.0", false)]
[InlineData("text/plain;missingparam=4;", "*/*;charset=utf-8;foo=bar;q=0.0", false)]
public void MediaTypeHeaderValue_IsSubTypeTests(string mediaType1, // Example: Formatter's supported media type
string mediaType2, // Example: Accept header media type
bool isMediaType1Subset)
{
// Arrange
var parsedMediaType1 = MediaTypeWithQualityHeaderValue.Parse(mediaType1);
var parsedMediaType2 = MediaTypeWithQualityHeaderValue.Parse(mediaType2);
// Act
var isSubset = parsedMediaType1.IsSubsetOf(parsedMediaType2);
// Assert
Assert.Equal(isMediaType1Subset, isSubset);
}
[Theory]
[InlineData("text/plain;charset=utf-16;foo=bar", "text/plain;charset=utf-8;foo=bar")]
[InlineData("text/plain;charset=utf-16;foo=bar", "text/plain;charset=utf-16;foo=bar1")]
[InlineData("text/plain;charset=utf-16;foo=bar", "text/json;charset=utf-16;foo=bar")]
[InlineData("text/plain;charset=utf-16;foo=bar", "application/plain;charset=utf-16;foo=bar")]
[InlineData("text/plain;charset=utf-16;foo=bar", "application/json;charset=utf-8;foo=bar1")]
[InlineData("text/plain; charset=utf-16; foo=bar", "application/json;charset=utf-8;foo=bar1")]
[InlineData("text/plain;charset = utf-16;foo = bar", "application/json;charset=utf-8;foo=bar1")]
public void MediaTypeHeaderValue_UpdateValue_RawValueGetsUpdated(string mediaTypeValue,
string expectedRawValue)
{
// Arrange
var parsedOldValue = MediaTypeHeaderValue.Parse(mediaTypeValue);
var parsedNewValue = MediaTypeHeaderValue.Parse(expectedRawValue);
// Act
parsedOldValue.Charset = parsedNewValue.Charset;
parsedOldValue.Parameters = parsedNewValue.Parameters;
parsedOldValue.MediaType = parsedNewValue.MediaType;
parsedOldValue.MediaSubType = parsedNewValue.MediaSubType;
parsedOldValue.MediaTypeRange = parsedNewValue.MediaTypeRange;
// Assert
Assert.Equal(expectedRawValue, parsedOldValue.RawValue);
}
private static void ValidateParametes(IDictionary<string, string> expectedParameters,
IDictionary<string, string> actualParameters)
{
Assert.Equal(expectedParameters.Count, actualParameters.Count);
foreach (var key in expectedParameters.Keys)
{
Assert.Equal(expectedParameters[key], actualParameters[key]);
}
}
}
}

View File

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.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>e69fd235-2042-43a4-9970-59cb29955b4e</ProjectGuid>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

View File

@ -1,56 +0,0 @@
// 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 Xunit;
namespace Microsoft.AspNet.Mvc.HeaderValueAbstractions
{
public class StringWithQualityHeaderValueParsingTests
{
[Theory]
[InlineData("*", HttpHeaderUtilitites.Match, "*")]
[InlineData("*", 0.7, "*;q=.7")]
[InlineData("iso-8859-5", HttpHeaderUtilitites.Match, "iso-8859-5")]
[InlineData("unicode-1-1", 0.8, "unicode-1-1;q=0.8")]
[InlineData("unicode-1-1", 0.8, "unicode-1-1;q =0.8")]
[InlineData("unicode-1-1", 0.8, "unicode-1-1;q = 0.8")]
[InlineData("unicode-1-1", 1.0, "unicode-1-1;quxx = 0.8")] // quxx gets ignored.
public void StringWithQualityHeaderValue_ParseSuccessfully(string value,
double quality,
string rawValue)
{
// Arrange
var parsedValue = StringWithQualityHeaderValue.Parse(rawValue);
// Act and Assert
Assert.Equal(rawValue, parsedValue.RawValue);
Assert.Equal(value, parsedValue.Value);
Assert.Equal(quality, parsedValue.Quality);
}
[Theory]
[InlineData("*", true, 0.7, "*;q=.7")]
[InlineData("iso-8859-5", true, HttpHeaderUtilitites.Match, "iso-8859-5")]
[InlineData("unicode-1-1", true, 0.8, "unicode-1-1;q=0.8")]
[InlineData("unicode-1-1", false, 0.8, "unicode-1-1;q=-")]
public void StringWithQualityHeaderValue_TryParse_ReturnsApproperiateResults(
string value,
bool result,
double quality,
string rawValue)
{
// Arrange
StringWithQualityHeaderValue parsedValue;
var isValid = StringWithQualityHeaderValue.TryParse(rawValue, out parsedValue);
// Act and Assert
Assert.Equal(result, isValid);
if(result == true)
{
Assert.Equal(rawValue, parsedValue.RawValue);
Assert.Equal(value, parsedValue.Value);
Assert.Equal(quality, parsedValue.Quality);
}
}
}
}

View File

@ -1,14 +0,0 @@
{
"dependencies": {
"Microsoft.AspNet.Mvc.HeaderValueAbstractions": "1.0.0-*",
"Microsoft.AspNet.Testing": "1.0.0-*",
"xunit.runner.kre": "1.0.0-*"
},
"commands": {
"test": "xunit.runner.kre"
},
"frameworks": {
"aspnet50": { },
"aspnetcore50": { }
}
}

View File

@ -68,7 +68,7 @@ namespace ApiExplorerWebSite
var responseData = new ApiExplorerResponseData()
{
FormatterType = response.Formatter.GetType().FullName,
MediaType = response.MediaType.RawValue,
MediaType = response.MediaType.ToString(),
};
data.SupportedResponseFormats.Add(responseData);

View File

@ -5,7 +5,7 @@ using System;
using System.Collections.Generic;
using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc.Description;
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
using Microsoft.Net.Http.Headers;
namespace ApiExplorerWebSite
{

View File

@ -2,7 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
using Microsoft.Net.Http.Headers;
using Newtonsoft.Json.Serialization;
namespace BasicWebSite.Controllers

View File

@ -2,7 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
using Microsoft.Net.Http.Headers;
namespace ConnegWebSite
{

View File

@ -5,7 +5,7 @@ using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
using Microsoft.Net.Http.Headers;
namespace ConnegWebSite
{

View File

@ -5,7 +5,7 @@ using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
using Microsoft.Net.Http.Headers;
namespace ConnegWebSite
{

View File

@ -8,7 +8,7 @@ using System.Text;
using System.Threading.Tasks;
using ConnegWebSite.Models;
using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
using Microsoft.Net.Http.Headers;
namespace ConnegWebSite
{

View File

@ -8,7 +8,7 @@ using System.Text;
using System.Threading.Tasks;
using ConnegWebSite.Models;
using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
using Microsoft.Net.Http.Headers;
namespace ConnegWebSite
{