WCF - 如何正确配置消耗WCF服务的MVC客户端?

时间:2016-07-25 10:02:55

标签: asp.net-mvc wcf webhttpbinding wcf-configuration

我完全清楚这个问题已经被讨论了很多次,但是这是我项目的一个特定配置,我想念它,这使得我的服务 - 客户端通信出错了。我在这件事上请求你的帮助。请原谅我的愚蠢错误,我对WCF和REST服务一般都很陌生。

所以,基本上,我想创建一个MVC应用程序,它将使用IIS服务器上托管的WCF REST服务。

我创建了一个WCF服务应用程序,其中包含以下服务合同

[ServiceContract]
public interface IUserService
{
    [OperationContract]
    [WebInvoke(Method = "GET",
        ResponseFormat = WebMessageFormat.Json,
        RequestFormat = WebMessageFormat.Json,
        BodyStyle = WebMessageBodyStyle.Wrapped,
        UriTemplate = "/ListaUtilizatori/")]
    DataSet ListaUtilizatori();

    [OperationContract]
    [WebInvoke(Method = "GET",
        ResponseFormat = WebMessageFormat.Json,
        RequestFormat = WebMessageFormat.Json,
        BodyStyle = WebMessageBodyStyle.Wrapped,
        UriTemplate = "/DetaliiUtilizator/{id}")]
    DataSet DetaliiUtilizator(String id);


    [OperationContract]
    [WebInvoke(Method = "POST",
        ResponseFormat = WebMessageFormat.Json,
        RequestFormat = WebMessageFormat.Json,
        BodyStyle = WebMessageBodyStyle.Wrapped,
        UriTemplate = "/AdaugaUtilizator")]
    String AdaugaUtilizator(Utilizator utilizator);

    [OperationContract]
    [WebInvoke(Method = "PUT",
      RequestFormat = WebMessageFormat.Json,
      ResponseFormat = WebMessageFormat.Json,
      UriTemplate = "/ActualizeazaUtilizator")]
    String ActualizeazaUtilizator(Utilizator utilizator);

    [OperationContract]
    [WebInvoke(Method = "DELETE",
       RequestFormat = WebMessageFormat.Json,
       ResponseFormat = WebMessageFormat.Json,
       UriTemplate = "/StergeUtilizator/{id}")]
    String StergeUtilizator(String id);
}

我正确地实现了这些方法,并在web.config文件中配置了服务模型:

<system.serviceModel>
    <services>
      <service name="RESTService.UserService" behaviorConfiguration="RESTServiceBehaviour">
        <endpoint address="" binding="webHttpBinding" bindingConfiguration="WebHttpBinding_IUserService" contract="RESTService.IUserService" behaviorConfiguration="RESTEndpointBehavior"></endpoint>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>        
        <behavior name="RESTServiceBehaviour">
          <!-- To avoid disclosing metadata information, set the values below to false before deployment -->
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
          <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior>
      </serviceBehaviors>
      <endpointBehaviors>
        <behavior name="RESTEndpointBehavior">
          <webHttp helpEnabled="True"/>
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <bindings>
      <webHttpBinding>
        <binding name="WebHttpBinding_IUserService" />
      </webHttpBinding>
    </bindings>
    <protocolMapping>
        <add binding="webHttpBinding" scheme="http" />
    </protocolMapping>    
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
  </system.serviceModel>

之后,我在IIS服务器上发布了WCF应用程序,它在浏览器中返回了预期的JSON格式响应。

我创建了一个MVC应用程序,我向其添加了对已发布的WCF服务的服务引用,并将其命名为UserServiceReference。奇怪的是,MVC的system.serviceModel中没有添加或配置web.config节点,所以我手动添加了以下内容:

<system.serviceModel>
    <behaviors>
      <endpointBehaviors>
        <behavior name="RESTEndpoint">
          <webHttp helpEnabled="true"/>
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <bindings>
      <webHttpBinding>
        <binding name="WebHttpBinding_IUserService" />        
      </webHttpBinding>      
    </bindings>
    <client>
      <endpoint address="http://localhost/RESTUserService/UserService.svc" binding="webHttpBinding" bindingConfiguration="WebHttpBinding_IUserService" 
                behaviorConfiguration="RESTEndpoint" contract="UserServiceReference.IUserService" name="WebHttpBinding_IUserService" />
    </client>
</system.serviceModel>

然后我尝试使用以下代码在其中一个应用程序控制器中创建客户端来测试功能:

UserServiceReference.UserServiceClient client = new UserServiceReference.UserServiceClient();
            DataSet ds = client.DetaliiUtilizator("2");
UserServiceReference.UserDataContractUtilizator utilizator = new UserServiceReference.UserDataContractUtilizator();

当我运行我的应用时,我在浏览器中收到此错误:

[WebException: The remote server returned an error: (404) Not Found.]  System.Net.HttpWebRequest.GetResponse() +1390    System.ServiceModel.Channels.HttpChannelRequest.WaitForReply(TimeSpan timeout) +55

[EndpointNotFoundException: There was no endpoint listening at http://localhost/RESTUserService/UserService.svc/DetaliiUtilizator that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.]
System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) +153



System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) +336
   MVCApp.UserServiceReference.IUserService.DetaliiUtilizator(String id) +0
   MVCApp.UserServiceReference.UserServiceClient.DetaliiUtilizator(String id) in D:\F5IT\PROJECT\RESTService\MVCApp\Service References\UserServiceReference\Reference.cs:308
   MVCApp.Controllers.HomeController.Index() in D:\F5IT\PROJECT\RESTService\MVCApp\Controllers\HomeController.cs:34
   lambda_method(Closure , ControllerBase , Object[] ) +61
   System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters) +14
   System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters) +157
   System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +27
   System.Web.Mvc.Async.AsyncControllerActionInvoker.<BeginInvokeSynchronousActionMethod>b__39(IAsyncResult asyncResult, ActionInvocation innerInvokeState) +22
   System.Web.Mvc.Async.WrappedAsyncResult`2.CallEndDelegate(IAsyncResult asyncResult) +29
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
   System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult) +32
   System.Web.Mvc.Async.AsyncInvocationWithFilters.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3d() +50
   System.Web.Mvc.Async.<>c__DisplayClass46.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3f() +225
   System.Web.Mvc.Async.<>c__DisplayClass33.<BeginInvokeActionMethodWithFilters>b__32(IAsyncResult asyncResult) +10
   System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +10
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
   System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethodWithFilters(IAsyncResult asyncResult) +34
   System.Web.Mvc.Async.<>c__DisplayClass2b.<BeginInvokeAction>b__1c() +26
   System.Web.Mvc.Async.<>c__DisplayClass21.<BeginInvokeAction>b__1e(IAsyncResult asyncResult) +100
   System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +10
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
   System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult) +27
   System.Web.Mvc.Controller.<BeginExecuteCore>b__1d(IAsyncResult asyncResult, ExecuteCoreState innerState) +13
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +29
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
   System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +36
   System.Web.Mvc.Controller.<BeginExecute>b__15(IAsyncResult asyncResult, Controller controller) +12
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +22
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
   System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +26
   System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult) +10
   System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__5(IAsyncResult asyncResult, ProcessRequestState innerState) +21
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +29
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
   System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +28
   System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +9
   System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +9744373
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155
Source Error: 

Line 306:        
Line 307:        public System.Data.DataSet DetaliiUtilizator(string id) {
Line 308:            return base.Channel.DetaliiUtilizator(id);
Line 309:        }
Line 310:     

我将这些内容添加为我阅读过的所有帖子的汇编。它必须是所有这些代码中的某个错误。会是什么呢?

非常感谢你!

1 个答案:

答案 0 :(得分:0)

我最终意识到这篇文章中存在哪个问题:

https://blogs.msdn.microsoft.com/carlosfigueira/2012/03/25/mixing-add-service-reference-and-wcf-web-http-a-k-a-rest-endpoint-does-not-work/

使用WebHttpBinding向端点添加服务引用似乎会导致无用的自动生成的客户端代码。