我正在使用WebScriptServiceHostFactory
构建WCF休息服务以支持POX和Json消息格式,并实现了自定义属性来处理操作的授权。我想将状态代码作为响应发送,并结束对未授权请求的请求,这样我就会在IErrorHandler
中从自定义属性和处理中抛出异常。但我无法将状态代码发送给客户。
我的HTTP状态代码为202(“已接受”),而不是401(“未经授权”)。
以下代码有什么问题吗?
[ServiceContract]
public interface Irestservice
{
[OperationContract]
[WebGet]
bool signin(string username, string password);
}
[ServiceBehavior(IncludeExceptionDetailInFaults = true,
InstanceContextMode = InstanceContextMode.PerCall),
AspNetCompatibilityRequirements(RequirementsMode =
AspNetCompatibilityRequirementsMode.Allowed)]
public class restservice : Irestservice
{
[Authorization]
public bool signin(string username, string password)
{
return true;
}
}
public class AuthorizationAttribute : Attribute, IOperationBehavior,
IParameterInspector
{
public void ApplyDispatchBehavior(
OperationDescription operationDescription,
DispatchOperation dispatchOperation)
{
dispatchOperation.ParameterInspectors.Add(this);
}
public void AfterCall(string operationName, object[] outputs,
object returnValue, object correlationState)
{
}
public object BeforeCall(string operationName, object[] inputs)
{
string publicKey = WebOperationContext.Current
.IncomingRequest.Headers["Authorization"];
bool flag = AuthorizationHelper.CheckPartnerAuthorization( publicKey);
if (!flag)
{
WebOperationContext.Current.OutgoingResponse.StatusCode =
HttpStatusCode.Unauthorized;
throw new LicensingException("PartnerUnauthorized");
}
return null;
}
}
public class LicensingBehavior : IServiceBehavior
{
public void ApplyDispatchBehavior(ServiceDescription serviceDescription,
ServiceHostBase serviceHostBase)
{
foreach (ChannelDispatcher channelDispatcher in
serviceHostBase.ChannelDispatchers)
{
RestErrorHandler newHandler = new RestErrorHandler();
channelDispatcher.ErrorHandlers.Add(newHandler);
}
}
}
class AppServiceHostFactory : WebScriptServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType,
Uri[] baseAddresses)
{
ServiceHost serviceHost =
base.CreateServiceHost(serviceType, baseAddresses);
serviceHost.Description.Behaviors.Add(new LicensingBehavior());
return serviceHost;
}
}
public class RestErrorHandler:IErrorHandler
{
#region IErrorHandler Members
public bool HandleError(Exception error)
{
return error is LicensingException;
}
public void ProvideFault(Exception error, MessageVersion version,
ref Message fault)
{
LicensingException licensingException = error as LicensingException;
if (licensingException != null)
{
fault = Message.CreateMessage(version, null,
new ValidationErrorBodyWriter(licensingException));
HttpResponseMessageProperty prop =
new HttpResponseMessageProperty();
prop.StatusCode = HttpStatusCode.Unauthorized;
prop.Headers[HttpResponseHeader.ContentType] =
"application/json; charset=utf-8";
fault.Properties.Add(HttpResponseMessageProperty.Name, prop);
fault.Properties.Add(WebBodyFormatMessageProperty.Name,
new WebBodyFormatMessageProperty(WebContentFormat.Json));
}
}
class ValidationErrorBodyWriter : BodyWriter
{
private LicensingException licensingException;
Encoding utf8Encoding = new UTF8Encoding(false);
public ValidationErrorBodyWriter(LicensingException exception)
: base(true)
{
this.licensingException = exception;
}
protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
{
writer.WriteStartElement("root");
writer.WriteAttributeString("type", "object");
writer.WriteStartElement("ErrorMessage");
writer.WriteAttributeString("type", "string");
writer.WriteString(this.licensingException.Message);
writer.WriteEndElement();
writer.WriteEndElement();
}
}
}
答案 0 :(得分:0)
您确定IErrorHandler接收的错误实际上是许可例外吗?请查看此post on error handling for webHttpBinding以确保您已正确实施ProvideFault方法。
答案 1 :(得分:0)
我正在使用工厂和serice配置。因此,工厂的行为掩盖了服务行为。因此,工厂和服务配置不应该一起使用。
答案 2 :(得分:0)
尝试在RestErrorHandler.ProvideFault中执行此操作:
var response = WebOperationContext.Current.OutgoingResponse;
response.StatusCode = HttpStatusCode.Unauthorized;