gpt4 book ai didi

wcf - 如何在 ASP.NET 应用程序中创建 WCF Web 服务,该服务可以将接口(interface)实例作为透明代理返回

转载 作者:行者123 更新时间:2023-12-05 01:25:50 28 4
gpt4 key购买 nike

我的用例:

  • 我已经有一个工作的 ASP.NET 应用程序
  • 我想实现一个新的 Web 服务作为该应用程序的一部分
  • 我应该使用 WCF 服务 (*.svc),而不是 ASP.NET Web 服务 (*.asmx)
  • 服务需要一个操作,我们称之为GetInterface() ,它返回一个接口(interface)的实例。该实例必须驻留在服务器上,而不是序列化到客户端;在该接口(interface)上调用的方法必须在服务器上执行。

  • 这是我尝试过的(请告诉我哪里出错了):
  • 为了对此进行测试,我创建了一个名为 ServiceSide 的新 ASP.NET Web 应用程序项目。 .
  • 在那个项目中,我使用“添加→新项目”添加了一个 WCF 服务。我叫它MainService .这创建了两个 MainService类以及 IMainService界面。
  • 现在我创建了一个名为 ServiceWorkLibrary 的新类库项目。仅包含要在客户端和服务器之间共享的接口(interface)声明,仅包含以下内容:
    [ServiceContract]
    public interface IWorkInterface
    {
    [OperationContract]
    int GetInt();
    }
  • 返回 ServiceSide ,我替换了默认的DoWork() IMainService 中的方法MainService 中的接口(interface)及其实现类,我还为共享 IWorkInterface 添加了一个简单的实现.它们现在看起来像这样:
    [ServiceContract]
    public interface IMainService
    {
    [OperationContract]
    IWorkInterface GetInterface();
    }

    public class MainService : IMainService
    {
    public IWorkInterface GetInterface()
    {
    return new WorkInterfaceImpl();
    }
    }

    public class WorkInterfaceImpl : MarshalByRefObject, IWorkInterface
    {
    public int GetInt() { return 47; }
    }

    现在运行这个应用程序“工作”,因为它在浏览器中为我提供了默认的 Web 服务页面,其中显示:

    You have created a service.

    To test this service, you will need to create a client and use it to call the service. You can do this using the svcutil.exe tool from the command line with the following syntax:

    svcutil.exe http://localhost:59958/MainService.svc?wsdl

    This will generate a configuration file and a code file that contains the client class. Add the two files to your client application and use the generated client class to call the Service. For example:

  • 那么就到客户端了。在单独的 Visual Studio 中,我创建了一个名为 ClientSide 的新控制台应用程序项目。有了新的解决方案。我添加了 ServiceWorkLibrary项目并添加了来自 ClientSide 的引用.
  • 然后我跑了上面的svcutil.exe称呼。这产生了 MainService.csoutput.config ,我添加到 ClientSide项目。
  • 最后,我将以下代码添加到 Main方法:
    using (var client = new MainServiceClient())
    {
    var workInterface = client.GetInterface();
    Console.WriteLine(workInterface.GetType().FullName);
    }
  • 这已经失败,在构造函数调用中出现了一个神秘的异常。我设法通过重命名 output.config 来解决这个问题至App.config .
  • 我注意到 GetInterface() 的返回类型是 object而不是 IWorkInterface .有谁知道为什么?但是让我们继续...
  • 现在,当我运行它时,我得到一个 CommunicationException调用GetInterface()时:

    The underlying connection was closed: The connection was closed unexpectedly.


  • 如何解决此问题,以便获得 IWorkInterface我期望的透明代理?

    我尝试过的事情
  • 我尝试添加 [KnownType(typeof(WorkInterfaceImpl))]WorkInterfaceImpl 的声明.如果我这样做,我会在同一个地方得到一个不同的异常。现在是 NetDispatcherFaultException留言:

    The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://tempuri.org/:GetInterfaceResult. The InnerException message was 'Error in line 1 position 491. Element 'http://tempuri.org/:GetInterfaceResult' contains data from a type that maps to the name 'http://schemas.datacontract.org/2004/07/ServiceSide:WorkInterfaceImpl'. The deserializer has no knowledge of any type that maps to this name. Consider using a DataContractResolver or add the type corresponding to 'WorkInterfaceImpl' to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding it to the list of known types passed to DataContractSerializer.'. Please see InnerException for more details.


    InnerException提到的是 SerializationException留言:

    Error in line 1 position 491. Element 'http://tempuri.org/:GetInterfaceResult' contains data from a type that maps to the name 'http://schemas.datacontract.org/2004/07/ServiceSide:WorkInterfaceImpl'. The deserializer has no knowledge of any type that maps to this name. Consider using a DataContractResolver or add the type corresponding to 'WorkInterfaceImpl' to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding it to the list of known types passed to DataContractSerializer.



    请注意这似乎表明系统正在尝试序列化该类型。 它不应该那样做。 它应该生成一个透明代理。我如何告诉它停止尝试序列化它?
  • 我尝试添加一个属性 [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)] , 到 WorkInterfaceImpl类(class)。没有效果。
  • 我尝试更改属性 [ServiceContract]IWorkInterfaceServiceWorkLibrary 的接口(interface)(在共享库[ServiceContract(SessionMode = SessionMode.Required)] 中声明) .也没有效果。
  • 我还尝试添加以下魔法 system.diagnostics Web.config 的元素在 ServerSide :
      <system.diagnostics>
    <!-- This logging is great when WCF does not work. -->
    <sources>
    <source name="System.ServiceModel" switchValue="Information, ActivityTracing" propagateActivity="true">
    <listeners>
    <add name="traceListener" type="System.Diagnostics.XmlWriterTraceListener" initializeData="c:\traces.svclog" />
    </listeners>
    </source>
    </sources>
    </system.diagnostics>

    这确实会生成 c:\traces.svclog按 promise 提交文件,但我不确定我能理解它的内容。 I’ve posted the generated file to pastebin here.您可以使用 svctraceviewer.exe 在更友好的 UI 中查看此信息。 .我这样做了,但坦率地说,所有这些东西并没有告诉我任何事情......

  • 我究竟做错了什么?

    最佳答案

    WCF 不直接支持我所描述的用例。

    可接受的解决方法是返回 EndpointAddress10 的实例它指向“其他”接口(interface)的服务。然后客户端必须手动创建一个 Channel 来访问远程对象。 WCF 没有正确封装这个过程。

    the MSDN article “From .NET Remoting to the Windows Communication Foundation (WCF)” 链接到一个示例来说明这一点。 (找到“单击此处下载本文的代码示例”的文本)。此示例代码演示了 .NET Remoting 和 WCF。它定义了一个如下所示的接口(interface):

    [ServiceContract]
    public interface IRemoteFactory
    {
    IMySessionBoundObject GetInstance();
    [OperationContract]
    EndpointAddress10 GetInstanceAddress();
    }

    请注意,接口(interface)返回方法不是契约(Contract)的一部分,只是返回 EndpointAddress10 的方法。标有 [OperationContract] .该示例通过 Remoting 调用第一个方法,它正确地创建了一个远程代理,正如人们所期望的那样——但是当使用 WCF 时,它求助于第二个方法,然后实例化一个单独的 ChannelFactory。使用新端点地址访问新对象。

    关于wcf - 如何在 ASP.NET 应用程序中创建 WCF Web 服务,该服务可以将接口(interface)实例作为透明代理返回,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9178604/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com