【问题标题】:Call the method automatically for each and every request in the WCF REST为 WCF REST 中的每个请求自动调用该方法
【发布时间】:2014-10-12 09:05:03
【问题描述】:

我有一个 WCF Rest 服务,在调用服务方法时,我们需要验证作为每个请求消息的一部分的许可证密钥(请求和响应消息将是 JSON 格式)。要验证许可证密钥,我们需要为每个请求调用单独的方法,该方法将包含如下逻辑,如果输入请求包含无效的许可证密钥,那么我们需要在 JSON 中发送“无效的许可证密钥”之类的错误消息格式发给客户端。 为此,我们在 WCF Rest 中是否有任何方法可以自动为每个请求调用此方法,而不是为每个请求显式调用?

注意:-许可证密钥将在 Service Web.Config 文件中提供。

【问题讨论】:

    标签: json wcf rest wcf-rest


    【解决方案1】:

    您可以使用消息检查器,该检查器会在每个到达服务的请求时调用。下面的代码显示了这种检查器的一种实现。

    public class StackOverflow_25380450
    {
        [ServiceContract]
        public class Service
        {
            [WebGet]
            public int Add(int x, int y)
            {
                return x + y;
            }
        }
    
        public class MyInspector : IDispatchMessageInspector, IEndpointBehavior
        {
            public const string LicenseHeaderName = "X-License";
            public const string ExpectedLicense = "abcdef";
    
            public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
            {
                HttpRequestMessageProperty reqProp = (HttpRequestMessageProperty)request.Properties[HttpRequestMessageProperty.Name];
                var license = reqProp.Headers[LicenseHeaderName];
                if (license != ExpectedLicense)
                {
                    throw new WebFaultException<string>("License required", HttpStatusCode.Forbidden);
                }
    
                return null;
            }
    
            public void BeforeSendReply(ref Message reply, object correlationState)
            {
            }
    
            public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
            {
            }
    
            public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
            {
            }
    
            public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
            {
                endpointDispatcher.DispatchRuntime.MessageInspectors.Add(this);
            }
    
            public void Validate(ServiceEndpoint endpoint)
            {
            }
        }
    
        public static string SendGet(string uri, Dictionary<string, string> headers)
        {
            string responseBody = null;
    
            HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(uri);
            req.Method = "GET";
            if (headers != null)
            {
                foreach (string headerName in headers.Keys)
                {
                    switch (headerName)
                    {
                        case "Accept":
                            req.Accept = headers[headerName];
                            break;
                        default:
                            req.Headers[headerName] = headers[headerName];
                            break;
                    }
                }
            }
    
            HttpWebResponse resp;
            try
            {
                resp = (HttpWebResponse)req.GetResponse();
            }
            catch (WebException e)
            {
                resp = (HttpWebResponse)e.Response;
            }
    
            if (resp == null)
            {
                responseBody = null;
                Console.WriteLine("Response is null");
            }
            else
            {
                Console.WriteLine("HTTP/{0} {1} {2}", resp.ProtocolVersion, (int)resp.StatusCode, resp.StatusDescription);
                foreach (string headerName in resp.Headers.AllKeys)
                {
                    Console.WriteLine("{0}: {1}", headerName, resp.Headers[headerName]);
                }
                Console.WriteLine();
                Stream respStream = resp.GetResponseStream();
                if (respStream != null)
                {
                    responseBody = new StreamReader(respStream).ReadToEnd();
                    Console.WriteLine(responseBody);
                }
                else
                {
                    Console.WriteLine("HttpWebResponse.GetResponseStream returned null");
                }
            }
    
            Console.WriteLine();
            Console.WriteLine("  *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*  ");
            Console.WriteLine();
    
            return responseBody;
        }
    
        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(Service), new WebHttpBinding(), "");
            endpoint.Behaviors.Add(new WebHttpBehavior { AutomaticFormatSelectionEnabled = true });
            endpoint.Behaviors.Add(new MyInspector());
            host.Open();
            Console.WriteLine("Host opened");
    
            Console.WriteLine("No license:");
            Dictionary<string, string> headers = new Dictionary<string, string>
            {
                { "Accept", "application/json" }
            };
            SendGet(baseAddress + "/Add?x=6&y=8", headers);
    
            Console.WriteLine("Incorrect license:");
            headers.Add(MyInspector.LicenseHeaderName, "incorrect");
            SendGet(baseAddress + "/Add?x=6&y=8", headers);
    
            headers[MyInspector.LicenseHeaderName] = MyInspector.ExpectedLicense;
            SendGet(baseAddress + "/Add?x=6&y=8", headers);
    
            Console.Write("Press ENTER to close the host");
            Console.ReadLine();
            host.Close();
        }
    }
    

    您可以在http://blogs.msdn.com/b/carlosfigueira/archive/2011/04/19/wcf-extensibility-message-inspectors.aspx 找到更多关于检查员的一般信息。

    【讨论】:

    • 这是我所期望的。感谢分享这个。以您的代码为基础,我已参考this blog。这是非常有用的。最后我很高兴得到可执行代码。
    • 需要一个小说明,如何从正文而不是标题中检索许可证密钥?
    • 如果密钥在正文中,那么您需要读取传递给AfterReceiveRequest 方法的request 参数。但请注意,Message 对象只能读取一次,因此在读取它之后,您需要创建一个新的Message 实例(参数通过引用传递的原因)以便可以读取消息再次由 WCF 管道的其余部分进行。
    猜你喜欢
    • 1970-01-01
    • 2019-01-05
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-22
    • 1970-01-01
    相关资源
    最近更新 更多