将 WCF 服务转换为 RESTful 应用程序?

2023-11-23

嘿,我在将 wcf 变成一项轻松的服务方面没有取得任何进展。所以我想知道当您在此处启动 WCF 服务应用程序时是否有人可以获取基本代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;

namespace WcfService1
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IService1" in both code and config file together.
    [ServiceContract]
    public interface IService1
    {

        [OperationContract]
        string GetData(int value);

        [OperationContract]
        CompositeType GetDataUsingDataContract(CompositeType composite);

        // TODO: Add your service operations here
    }


    // Use a data contract as illustrated in the sample below to add composite types to service operations.
    [DataContract]
    public class CompositeType
    {
        bool boolValue = true;
        string stringValue = "Hello ";

        [DataMember]
        public bool BoolValue
        {
            get { return boolValue; }
            set { boolValue = value; }
        }

        [DataMember]
        public string StringValue
        {
            get { return stringValue; }
            set { stringValue = value; }
        }
    }
}

和服务:

namespace WcfService1
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in code, svc and config file together.
    public class Service1 : IService1
    {
        public string GetData(int value)
        {
            return string.Format("You entered: {0}", value);
        }

        public CompositeType GetDataUsingDataContract(CompositeType composite)
        {
            if (composite == null)
            {
                throw new ArgumentNullException("composite");
            }
            if (composite.BoolValue)
            {
                composite.StringValue += "Suffix";
            }
            return composite;
        }
    }
}

我所做的就是启动这个 WCF 服务应用程序,并打开另一个带有基本表单的 VS2010 灵魂,其中有一个文本框按钮和标签,并将 serviceapp 的服务位置复制到另一个解决方案中,这样当我输入一个数字时,我会得到来自服务。

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }
        public ServiceReference1.Service1Client testClient = new ServiceReference1.Service1Client();
        private void button1_Click(object sender, EventArgs e)
        {
            label1.Text = testClient.GetData(Convert.ToInt32(textBox1.Text));
        }
    }
}

确实又快又脏,但达到了目的。

现在,如果有人可以帮助编写代码,您如何将其转变为一项轻松的服务?

我的配置文件的结束部分:

 <system.serviceModel>
    <services>
      <service name="WcfService1.Service1" behaviorConfiguration="WcfService1.Service1Behavior">
        <!-- Service Endpoints -->
        <endpoint address="" binding="wsHttpBinding" contract="WcfService1.IService1">
          <!-- 
              Upon deployment, the following identity element should be removed or replaced to reflect the 
              identity under which the deployed service runs.  If removed, WCF will infer an appropriate identity 
              automatically.
          -->
          <identity>
            <dns value="localhost"/>
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="WcfService1.Service1Behavior">
          <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
          <serviceMetadata httpGetEnabled="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="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

</configuration>

使用 Justins 配置代码编辑更新:

因此,当我触摸配置文件时,我通常的错误是:无法添加服务。服务元数据可能无法访问。确保您的服务正在运行并公开元数据

Error: Cannot obtain Metadata from http://localhost:26535/Service1.svc If this is a Windows (R) Communication Foundation service to which you have access, please check that you have enabled metadata publishing at the specified address.  For help enabling metadata publishing, please refer to the MSDN documentation at http://go.microsoft.com/fwlink/?LinkId=65455.WS-Metadata Exchange Error    URI: http://localhost:26535/Service1.svc    Metadata contains a reference that cannot be resolved: 'http://localhost:26535/Service1.svc'.    The server did not provide a meaningful reply; this might be caused by a contract mismatch, a premature session shutdown or an internal server error.HTTP GET Error    URI: http://localhost:26535/Service1.svc    There was an error downloading 'http://localhost:26535/Service1.svc'.    The request failed with the error message:--<html>    <head>        <title>Operation 'GetData' in contract 'IService1' has a path variable named 'value' which does not have type 'string'. ÿVariables for UriTemplate path segments must have type 'string'.</title>        <style>         body {font-family:"Verdana";font-weight:normal;font-size: .7em;color:black;}          p {font-family:"Verdana";font-weight:normal;color:black;margin-top: -5px}         b {font-family:"Verdana";font-weight:bold;color:black;margin-top: -5px}         H1 { font-family:"Verdana";font-weight:normal;font-size:18pt;color:red }         H2 { font-family:"Verdana";font-weight:normal;font-size:14pt;color:maroon }         pre {font-family:"Lucida Console";font-size: .9em}         .marker {font-weight: bold; color: black;text-decoration: none;}         .version {color: gray;}         .error {margin-bottom: 10px;}         .expandable { text-decoration:underline; font-weight:bold; color:navy; cursor:hand; }        </style>    </head>    <body bgcolor="white">            <span><H1>Server Error in '/' Application.<hr width=100% size=1 color=silver></H1>            <h2> <i>Operation 'GetData' in contract 'IService1' has a path variable named 'value' which does not have type 'string'. ÿVariables for UriTemplate path segments must have type 'string'.</i> </h2></span>            <font face="Arial, Helvetica, Geneva, SunSans-Regular, sans-serif ">            <b> Description: </b>An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.            <br><br>            <b> Exception Details: </b>System.InvalidOperationException: Operation 'GetData' in contract 'IService1' has a path variable named 'value' which does not have type 'string'. ÿVariables for UriTemplate path segments must have type 'string'.<br><br>            <b>Source Error:</b> <br><br>            <table width=100% bgcolor="#ffffcc">               <tr>                  <td>                      <code>An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.</code>                  </td>               </tr>            </table>            <br>            <b>Stack Trace:</b> <br><br>            <table width=100% bgcolor="#ffffcc">               <tr>                  <td>                      <code><pre>[InvalidOperationException: Operation 'GetData' in contract 'IService1' has a path variable named 'value' which does not have type 'string'.  Variables for UriTemplate path segments must have type 'string'.]   System.ServiceModel.Dispatcher.UriTemplateClientFormatter.Populate(Dictionary`2& pathMapping, Dictionary`2& queryMapping, Int32& totalNumUTVars, UriTemplate& uriTemplate, OperationDescription operationDescription, QueryStringConverter qsc, String contractName) +726   System.ServiceModel.Dispatcher.UriTemplateDispatchFormatter..ctor(OperationDescription operationDescription, IDispatchMessageFormatter inner, QueryStringConverter qsc, String contractName, Uri baseAddress) +94   System.ServiceModel.Description.WebHttpBehavior.GetRequestDispatchFormatter(OperationDescription operationDescription, ServiceEndpoint endpoint) +137   System.ServiceModel.Description.WebHttpBehavior.ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) +659   System.ServiceModel.Description.DispatcherBuilder.InitializeServiceHost(ServiceDescription description, ServiceHostBase serviceHost) +3864   System.ServiceModel.ServiceHostBase.InitializeRuntime() +37   System.ServiceModel.ServiceHostBase.OnBeginOpen() +27   System.ServiceModel.ServiceHostBase.OnOpen(TimeSpan timeout) +49   System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +261   System.ServiceModel.HostingManager.ActivateService(String normalizedVirtualPath) +121   System.ServiceModel.HostingManager.EnsureServiceAvailable(String normalizedVirtualPath) +479[ServiceActivationException: The service '/Service1.svc' cannot be activated due to an exception during compilation.  The exception message is: Operation 'GetData' in contract 'IService1' has a path variable named 'value' which does not have type 'string'.  Variables for UriTemplate path segments must have type 'string'..]   System.ServiceModel.AsyncResult.End(IAsyncResult result) +11655726   System.ServiceModel.Activation.HostedHttpRequestAsyncResult.End(IAsyncResult result) +194   System.ServiceModel.Activation.HostedHttpRequestAsyncResult.ExecuteSynchronous(HttpApplication context, Boolean flowContext) +176   System.ServiceModel.Activation.HttpModule.ProcessRequest(Object sender, EventArgs e) +275   System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +68   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +75</pre></code>                  </td>               </tr>            </table>            <br>            <hr width=100% size=1 color=silver>            <b>Version Information:</b>ÿMicrosoft .NET Framework Version:2.0.50727.5448; ASP.NET Version:2.0.50727.5456            </font>    </body></html><!-- [InvalidOperationException]: Operation 'GetData' in contract 'IService1' has a path variable named 'value' which does not have type 'string'.  Variables for UriTemplate path segments must have type 'string'.   at System.ServiceModel.Dispatcher.UriTemplateClientFormatter.Populate(Dictionary`2& pathMapping, Dictionary`2& queryMapping, Int32& totalNumUTVars, UriTemplate& uriTemplate, OperationDescription operationDescription, QueryStringConverter qsc, String contractName)   at System.ServiceModel.Dispatcher.UriTemplateDispatchFormatter..ctor(OperationDescription operationDescription, IDispatchMessageFormatter inner, QueryStringConverter qsc, String contractName, Uri baseAddress)   at System.ServiceModel.Description.WebHttpBehavior.GetRequestDispatchFormatter(OperationDescription operationDescription, ServiceEndpoint endpoint)   at System.ServiceModel.Description.WebHttpBehavior.ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)   at System.ServiceModel.Description.DispatcherBuilder.InitializeServiceHost(ServiceDescription description, ServiceHostBase serviceHost)   at System.ServiceModel.ServiceHostBase.InitializeRuntime()   at System.ServiceModel.ServiceHostBase.OnBeginOpen()   at System.ServiceModel.ServiceHostBase.OnOpen(TimeSpan timeout)   at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)   at System.ServiceModel.ServiceHostingEnvironment.HostingManager.ActivateService(String normalizedVirtualPath)   at System.ServiceModel.ServiceHostingEnvironment.HostingManager.EnsureServiceAvailable(String normalizedVirtualPath)[ServiceActivationException]: The service '/Service1.svc' cannot be activated due to an exception during compilation.  The exception message is: Operation 'GetData' in contract 'IService1' has a path variable named 'value' which does not have type 'string'.  Variables for UriTemplate path segments must have type 'string'..   at System.ServiceModel.AsyncResult.End[TAsyncResult](IAsyncResult result)   at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.End(IAsyncResult result)   at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.ExecuteSynchronous(HttpApplication context, Boolean flowContext)   at System.ServiceModel.Activation.HttpModule.ProcessRequest(Object sender, EventArgs e)   at System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)-->--.

正如您所提到的,这是一个新项目,因此重定向可能有助于使过程变得更简单一些?

这是一篇关于您所问问题的 MSDN 文章.

不过,我特别建议看看服务栈创建 RESTful 服务,因为它使过程变得非常简单。 WCF 绝对没有提供完成此任务的简单方法。在我看来,他们在这种情况下过于复杂化了。

如果这确实是一个项目的开始,那将是我会选择的地方

更直接的答案来自这篇文章有点旧,但可能有助于理解 REST 以及如何在 WCF 中实现它。就是在 Web[Type]Attribute 中指定您的 GET/POST/PUT/DELETE

[WebGet(UriTemplate = @"Data?value={value}")]
[OperationContract]
string GetData(int value);

另外,您需要在应用程序的 .config 中执行此操作(同样对于较旧的,Skonnad 的 MSDN 文章)

<configuration>
   <system.serviceModel>
     <services>
        <service name="Service1">
            <endpoint binding="webHttpBinding" contract="Service1"
                      behaviorConfiguration="webHttp"/>
        </service>
     </services>
     <behaviors>
        <endpointBehaviors>
            <behavior name="webHttp">
                <webHttp/>
            </behavior>
        </endpointBehaviors>
     </behaviors>
  </system.serviceModel>
<configuration>

这将转化为您的配置:

<system.serviceModel>
<services>
  <service name="WcfService1.Service1"
        behaviorConfiguration="WcfService1.Service1Behavior">
    <!-- Service Endpoints -->
    <endpoint address="" binding="webHttpBinding" contract="WcfService1.IService1"
        behaviorConfiguration="webHttp">
      <!-- 
          Upon deployment, the following identity element should be removed 
          or replaced to reflect the identity under which the deployed service runs.  
          If removed, WCF will infer an appropriate identity automatically.
      -->
      <identity>
        <dns value="localhost"/>
      </identity>
    </endpoint>
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
  </service>
</services>
<behaviors>
  <serviceBehaviors>
    <behavior name="WcfService1.Service1Behavior">
      <!-- To avoid disclosing metadata information, set the value below to false 
           and remove the metadata endpoint above before deployment -->
      <serviceMetadata httpGetEnabled="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="false"/>
    </behavior>
  </serviceBehaviors>
  <endpointBehaviors>
      <behavior name="webHttp">
           <webHttp/>
      </behavior>
  </endpointBehaviors>
</behaviors>

然后,您可能需要向端点添加地址属性,以便它知道要查找的位置。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将 WCF 服务转换为 RESTful 应用程序? 的相关文章

  • 如果两个线程同时访问同一个 bool 变量会发生什么?

    我有一个跨平台 C 程序 其中使用 boost 库创建异步计时器 我有一个全局变量 bool receivedInput false 一个线程等待并处理输入 string argStr while 1 getline cin argStr
  • 如何通知父线程所有子线程都已终止?

    我有一个控制台应用程序正在移植到 WPF 该应用程序有 3 个工作线程 在将一些输出结果打印到屏幕上之前 这些线程都连接到主线程 我的理解是 如果我尝试在 WPF 应用程序中执行相同的操作 GUI 将被阻止并且不会响应用户 那么如何通知父线
  • C++ 和序列化:有什么方法可以进行某种内省吗?

    我读过一些例子维基百科 http en wikipedia org wiki Type introspection C 2B 2B但我正在寻找一些现实生活中的例子 如何使用内省 为什么 它有助于编写干净的代码 以及代码本身 例如 有没有办法
  • C# 并行与并行线程代码性能

    我一直在测试 System Threading Parallel 与线程的性能 我很惊讶地发现并行比线程花费更长的时间来完成任务 我确信这是由于我对并行的了解有限 我刚刚开始阅读 我想我会分享一些片段 如果有人可以向我指出并行代码比线程代码
  • 将 void *user_data 转换为对象

    我该如何投射void something到标准 C 中的对象 具体来说我想投void userdata to std map
  • 计算复杂数组的abs()值的最快方法

    我想计算 C 或 C 中复杂数组元素的绝对值 最简单的方法是 for int i 0 i lt N i b i cabs a i 但对于大向量来说 速度会很慢 有没有办法加快速度 例如使用并行化 语言可以是 C 或 C 鉴于所有循环迭代都是
  • 我的 WPF 应用程序未触发 MainWindow_Loaded

    我目前正在关注Pluralsight C Fundamentals Part 1并在Classes and Objects视频部分指导我在 Visual Studio 中创建一个新的 WPF 应用程序并填写代码 这导致以下结果 namesp
  • 试图使用加密来混淆我的项目打破了它

    我试图尝试不同的混淆选项 为了做到这一点 我首先尝试了加密货币 以下是我遵循的步骤 打开加密向导并选择一些选项 选择我的解决方案文件 完成向导后 我看到有些 Dll 被很好地混淆了 但我的项目现在无法构建 我注意到的两件事是 我的文件夹中有
  • 从套接字读取 C HTTP

    我想知道如何判断是否已从套接字接收到所有数据 这是一个简单的网络代理 现在我正在处理请求部分 所以发送的内容应该以 r n r n 结尾 我不知道请求会持续多久 我在这里读过一些帖子 说我应该检查读取函数是否返回 0 但其他人说0只在客户端
  • 如何从Web JavaScript应用程序获取桌面C#程序中的变量

    我遇到一个问题 有两个应用程序 一种是 C 中的桌面应用程序 另一种是 javascript 中的 Web 应用程序 运行桌面应用程序中的一些变量或信息需要传输到Web应用程序 有谁知道如何解决这个问题 有人愿意提供更多细节来解决这个问题吗
  • Identity Server 4:添加访问令牌的声明

    我正在使用 Identity Server 4 和隐式流 并且想要向访问令牌添加一些声明 新的声明或属性是 tenantId 和 langId 我已将 langId 添加为我的范围之一 如下所示 然后通过身份服务器请求 但我也获得了tena
  • 我可以在 C++ 中重写非虚函数吗

    我想知道我可以重写 C 中的非虚函数吗 因为我在使用 C 时发现了这个问题override关键字我的代码如下 class A public void say cout lt lt From A n class B public A publ
  • 除空字符串外的任何内容的正则表达式

    是否可以使用正则表达式来检测任何不是 空字符串 的内容 如下所示 string s1 string s2 string s3 string s4 etc 我知道我可以使用修剪等 但我想使用正则表达式 s 将匹配任何包含至少一个非空格字符的字
  • 如何使用 ProtoGen 从 proto 文件生成结构

    我们一直在使用 protobuf net ProtoGen 从 proto 文件生成 C cs 文件 我们希望代替类来生成结构 例如 DataContract public struct Entity1 ProtoMember 1 publ
  • Request.Form 和 Request.QueryString 之间的区别?

    有人可以告诉我两者之间的确切区别吗Request Form and Request QueryString 我知道一个区别 比如 如果HTTP请求方式为POST 则用户提交的数据在申请表 收藏 如果HTTP请求方法是GET 则用户提交的数据
  • 为什么必须通过 this 指针访问模板基类成员?

    如果下面的类不是模板 我可以简单地拥有x in the derived班级 但是 通过下面的代码 我have to use this gt x Why template
  • #define 内存地址声明

    这个 define 语句有什么作用 它用于定义内存地址 但我不明白 uint32 t 部分 define GPxDAT uint32 t 0x6FC0 通常用于访问映射到地址空间的硬件寄存器 或者一些特定的内存地址 硬件寄存器应定义为vol
  • 云到设备 Azure IoT REST API

    我探索了如何使用 Azure REST API 将数据从设备发送到云 它运行无缝 没有任何问题 我没有找到有关使用 Azure IoT Hub REST API 向 Arduino 板发送云到设备消息的好文章 有人可以就此提供建议吗 您还可
  • 用于 nmap 输出的 C++ xml 解析器

    我是 nmap 的新手 我在 nmap 教程中看到 https nmap org book man output html https nmap org book man output html oX 选项可用于获取 xml 格式的 nma
  • C#:如何处理乱序 TCP 数据包?

    请有人解释一下如何处理乱序数据包 我使用原始套接字来捕获数据包 并在数据包到来时解析它们 但其中一些数据包的顺序错误 例如 ID 标志 16390 PSH ACK 16535 PSH ACK 16638 确认 16640 PSH ACK 1

随机推荐