WCF: один и тот же контракт на многие методы
Возьмем, к примеру, проект с 10 сервисами и 20 методами для каждого сервиса.
Все сервисы наследуются от базовой службы, которая имеет проверку безопасности. Первое, что делает каждый метод, это вызывает проверку безопасности. Это вызывает исключение безопасности, если есть проблема.
Вопрос: нужно ли указывать FaultContract для каждого метода (OperationContract) или я могу сделать это один раз в центральном определении?
3 ответа
Нет, вам нужно делать это на каждом методе - WCF довольно требователен и требует явных настроек практически для всего (что, в конце концов, на самом деле хорошо, я уверен).
Марк
Вы можете сделать это, создав собственный атрибут.
Реализуйте IContractBehavior и добавьте ошибку к каждой операции в методе Validate.
void IContractBehavior.Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
{
foreach (OperationDescription od in contractDescription.Operations)
od.Add(yourFault);
}
Вот ссылка, которая подробно описывает, как этого добиться. Ниже фактический код для использования:
[AttributeUsage(AttributeTargets.Interface, AllowMultiple = false, Inherited = true)]
public class StandardFaultsAttribute : Attribute, IContractBehavior
{
// this is a list of our standard fault detail classes.
static Type[] Faults = new Type[]
{
typeof(AuthFailure),
typeof(UnexpectedException),
typeof(UserFriendlyError)
};
public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
}
public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
{
}
public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
{
foreach (OperationDescription op in contractDescription.Operations)
{
foreach (Type fault in Faults)
{
op.Faults.Add(MakeFault(fault));
}
}
}
private FaultDescription MakeFault(Type detailType)
{
string action = detailType.Name;
DescriptionAttribute description = (DescriptionAttribute) Attribute.GetCustomAttribute(detailType, typeof(DescriptionAttribute));
if (description != null)
action = description.Description;
FaultDescription fd = new FaultDescription(action);
fd.DetailType = detailType;
fd.Name = detailType.Name;
return fd;
}
}