为RESTful WCF服务实现RequestWrapper

时间:2012-04-14 19:55:48

标签: wcf rest wrapper webhttpbinding

我写了一个名为 RequestWrapper 的简单对象,其中包含单一类型的方法:

TResult WrapRequest<TResult>(Func<TResult> action)

它包含try..catch,错误处理,日志记录,数据库连接,事务(提交和回滚)等任何操作。

目前我这样使用它:(例如,不是生产代码)

return RequestWrapper.WrapRequest(() =>
{
    Topic entity = GetRepository<Topic>().Find(uid);

    if (entity == null)
        throw new EntityNotFoundException("Topic not found.");

    return new Topic
    {
        Name = entity.Name,
        Posts = entity.Posts.Select(x => new Post
        {
            Body = x.Body,
        }).ToList()
    };
});

我只是简单地包含我的RESTful Web服务的每个方法(使用WCF和 WebHttpBinding )。

我的问题是:我应该如何实现自动包装的行为?有可能吗?

1 个答案:

答案 0 :(得分:4)

您可以使用自定义IOperationInvoker包裹原始的public class StackOverflow_10156890 { [ServiceContract] public interface ITest { [WebGet] [WrappedOperationBehavior] string Echo(string text); [WebInvoke(BodyStyle = WebMessageBodyStyle.WrappedRequest)] [WrappedOperationBehavior] int Divide(int x, int y); } public class Service : ITest { public string Echo(string text) { return text; } public int Divide(int x, int y) { return x / y; } } class RequestWrapperOperationInvoker : IOperationInvoker { IOperationInvoker originalInvoker; public RequestWrapperOperationInvoker(IOperationInvoker originalInvoker) { this.originalInvoker = originalInvoker; } public object[] AllocateInputs() { return this.originalInvoker.AllocateInputs(); } public object Invoke(object instance, object[] inputs, out object[] outputs) { Console.WriteLine("Do initialization, etc. here"); object result = null; try { result = this.originalInvoker.Invoke(instance, inputs, out outputs); } catch (Exception e) { Console.WriteLine("Log exception: {0}: {1}", e.GetType().FullName, e.Message); result = null; outputs = null; } finally { Console.WriteLine("Do finalization, etc. here"); } return result; } public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state) { throw new NotSupportedException("Only synchronous operations supported"); } public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result) { throw new NotSupportedException("Only synchronous operations supported"); } public bool IsSynchronous { get { return true; } } } class WrappedOperationBehaviorAttribute : Attribute, IOperationBehavior { public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters) { } public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation) { } public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation) { dispatchOperation.Invoker = new RequestWrapperOperationInvoker(dispatchOperation.Invoker); } public void Validate(OperationDescription operationDescription) { } } public static void Test() { string baseAddress = "http://" + Environment.MachineName + ":8000/Service"; ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress)); var endpoint = host.AddServiceEndpoint(typeof(ITest), new WebHttpBinding(), ""); endpoint.Behaviors.Add(new WebHttpBehavior()); host.Open(); Console.WriteLine("Host opened"); WebClient c = new WebClient(); Console.WriteLine(c.DownloadString(baseAddress + "/Echo?text=Hello%20world")); c = new WebClient(); c.Headers[HttpRequestHeader.ContentType] = "application/json"; Console.WriteLine(c.UploadString(baseAddress + "/Divide", "{\"x\":12,\"y\":0}")); Console.Write("Press ENTER to close the host"); Console.ReadLine(); host.Close(); } } 来满足您的需求。下面的代码显示了一个示例实现,您可以在http://blogs.msdn.com/b/carlosfigueira/archive/2011/05/17/wcf-extensibility-ioperationinvoker.aspx找到有关调用者的更多信息。

{{1}}