使用CORS Message Inspector的XML序列化未使用数据协定序列化 [英] XML Serialization using CORS Message Inspector is not using the Data Contract Serialization
问题描述
我们已经实现了当前的REST服务,该服务会返回类似以下项的列表:
We have a current REST service implemented that returns a list of items like this:
< Items xmlns ="http://schemas.datacontract.org/2004/07/Mns.DataProvider" xmlns:i ="http://www.w3.org/2001/XMLSchema-instance">
< Item i:type =" CalculatedItemInfo">
< StartDate> 2017-05-01T00:00:00</StartDate>
< StartValue> 0</StartValue>
< Type>绝对</Type>
<单位>无</单位>
< UserKey1> 1</UserKey1>
< UserKey2/>
< UserKey3/>
<计算/>
</Item>
< Item i:type =" StandardItemInfo">
<名称> AW特警|威尔兰|子集水区| LCALC</名称>
<计算/>
</Item>
<Items xmlns="http://schemas.datacontract.org/2004/07/Mns.DataProvider" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Item i:type="CalculatedItemInfo">
<StartDate>2017-05-01T00:00:00</StartDate>
<StartValue>0</StartValue>
<Type>Absolute</Type>
<Units>None</Units>
<UserKey1>1</UserKey1>
<UserKey2/>
<UserKey3/>
<Calculation/>
</Item>
<Item i:type="StandardItemInfo">
<Name>AW Swat|Welland|Subcatchment|LCALC</Name>
<Calculation/>
</Item>
列表上有一个DataContractAttribute,如下所示:
The list has a DataContractAttribute on it as follows:
[CollectionDataContract(Name =" Items"))]
公共类BaseItemInfos:List< BaseItemInfo>
{
}
[CollectionDataContract(Name = "Items")]
public class BaseItemInfos : List<BaseItemInfo>
{
}
一切正常.我现在添加了一个CORS消息检查器,因为我们需要支持相当标准的CORS:
which all works well. I have now added a CORS message inspector as we need to support CORS which is fairly standard:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Web;
using System.Text;
namespace Mns.WebService
{
public class CorsMessageInspector : IDispatchMessageInspector
{
private static readonly HashSet<string> s_helpPageUris = new HashSet<string>(new string[] { "GetHelpPage", "GetOperationHelpPage" }, StringComparer.OrdinalIgnoreCase);
private const string BasicPrefix = "basic ";
private static readonly int s_basicPrefixLength = BasicPrefix.Length;
private readonly bool m_enforceBasicAuthentication;
public CorsMessageInspector(bool enforceBasicAuthentication)
{
m_enforceBasicAuthentication = enforceBasicAuthentication;
}
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
// Check if the client sent a preflight request for CORS
HttpRequestMessageProperty httpRequest = request.Properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty;
if (httpRequest == null) return null;
string origin = httpRequest.Headers["Origin"];
if (!String.IsNullOrEmpty(origin)) OperationContext.Current.Extensions.Add(new CorsOperationContext(origin));
if (String.Equals(httpRequest.Method, "options", StringComparison.OrdinalIgnoreCase))
OperationContext.Current.Extensions.Add(new PreflightOperationContext(httpRequest.Headers["Access-Control-Request-Headers"])); // CORS Preflight
else if (m_enforceBasicAuthentication)
{
if (PasswordValidator == null) throw new WebFaultException<string>("Access denied", HttpStatusCode.Unauthorized);
// Allow help pages through without authentication
if ((WebOperationContext.Current.IncomingRequest.UriTemplateMatch != null) && s_helpPageUris.Contains(WebOperationContext.Current.IncomingRequest.UriTemplateMatch.Data.ToString())) return null;
// If not then authorize
string authorizationHeader = WebOperationContext.Current.IncomingRequest.Headers[HttpRequestHeader.Authorization];
if (!String.IsNullOrEmpty(authorizationHeader))
{
int basicIndex = authorizationHeader.IndexOf(BasicPrefix, StringComparison.OrdinalIgnoreCase);
if (basicIndex != -1)
{
string encodedUserNamePassword = authorizationHeader.Substring(basicIndex + s_basicPrefixLength);
if (!String.IsNullOrEmpty(encodedUserNamePassword))
{
string userNamePassword = null;
try
{
userNamePassword = ASCIIEncoding.ASCII.GetString(Convert.FromBase64String(encodedUserNamePassword));
}
catch (FormatException) { }
catch (ArgumentException) { }
if (!String.IsNullOrEmpty(userNamePassword))
{
int colonIndex = userNamePassword.IndexOf(":", StringComparison.OrdinalIgnoreCase);
if (colonIndex != -1)
{
string userName = userNamePassword.Substring(0, colonIndex);
string password = userNamePassword.Substring(colonIndex + 1);
if (!String.IsNullOrEmpty(userName))
{
PasswordValidator.Validate(userName, password);
AuthorizationOperationContext.Current.UserName = userName;
AuthorizationOperationContext.Current.ContentType = httpRequest.Headers["Content-Type"];
return null;
}
}
}
}
}
}
WebOperationContext.Current.OutgoingResponse.Headers.Add("WWW-Authenticate", @"Basic realm=""MCE""");
throw new WebFaultException<string>("Access denied", HttpStatusCode.Unauthorized);
}
return null;
}
public void BeforeSendReply(ref Message reply, object correlationState)
{
PreflightOperationContext preflightContext = OperationContext.Current.Extensions.Find<PreflightOperationContext>();
HttpResponseMessageProperty httpHeader = null;
if (preflightContext != null)
{
httpHeader = new HttpResponseMessageProperty() { StatusCode = HttpStatusCode.OK };
reply.Properties[HttpResponseMessageProperty.Name] = httpHeader;
}
else if (reply != null)
{
httpHeader = reply.Properties[HttpResponseMessageProperty.Name] as HttpResponseMessageProperty;
httpHeader.Headers["Content-Type"] = AuthorizationOperationContext.Current.ContentType;
reply.Properties[WebBodyFormatMessageProperty.Name] = new WebBodyFormatMessageProperty(AuthorizationOperationContext.Current.BodyFormat);
}
if (httpHeader != null)
{
CorsOperationContext corsContext = OperationContext.Current.Extensions.Find<CorsOperationContext>();
WebHeaderCollection headers = httpHeader.Headers;
if (preflightContext != null)
{
string requestedHeaders = preflightContext.RequestedHeaders;
if (!String.IsNullOrEmpty(requestedHeaders)) requestedHeaders += ", ";
requestedHeaders += "content-Type, accept, authorization";
headers.Add("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
headers.Add("Access-Control-Allow-Headers", requestedHeaders);
}
headers.Add("Access-Control-Allow-Credentials", "true");
headers.Add("Access-Control-Allow-Origin", (corsContext != null) ? corsContext.Origin : "*");
}
}
public static PasswordValidator PasswordValidator { get; set; }
}
}
现在我们使用的是CORS端点,XML返回如下:
Now we are using a CORS end point the XML is coming back as follows:
推荐答案
我认为需要做的是使用DataContractSerializer重写消息创建.
I think what needs to be done is the message creation needs to be overridden to use the DataContractSerializer.
如何使用消息检查器覆盖它?
How can I override this using a message inspector?
谢谢
伊恩
这篇关于使用CORS Message Inspector的XML序列化未使用数据协定序列化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!