简体   繁体   English

REST WCF数据服务的简单示例

[英]Simple example with REST WCF Data Service

I need to develop data transfer between two sites and believe that with our .Net environment a RESTful implementation would be much better than one with FTP (ugh). 我需要开发两个站点之间的数据传输,并相信使用我们的.Net环境,RESTful实现将比使用FTP (ugh)更好。 However, simple examples are hard to find, and the REST basics obscured by ADO.NET or lots of clever details, so I am trying to make one really simple myself. 但是,很难找到简单的示例,并且REST基础已被ADO.NET或许多巧妙的细节所遮盖,因此我试图使自己变得非常简单。 Still, I need some help on principles and implementation to get it to work. 尽管如此,我仍需要一些原则和实施方面的帮助才能使其正常工作。

In a VisualStudio web project I created a new item WCF Data Service and a class for the data. 在VisualStudio Web项目中,我创建了一个新项WCF Data Service和一个数据类。 This is App_Code\\WidgetRecord.cs: 这是App_Code \\ WidgetRecord.cs:

//using System;
using System.Collections.Generic;//List
using System.Linq;//Where
//using System.Web;
using System.ServiceModel;//ServiceContract, OperationContract
using System.Runtime.Serialization;//DataContract
using System.Diagnostics;//Debug.WriteLine()

/// <summary>
/// Declare operations for a service
/// </summary>
[ServiceContract]
public interface IScandataService
{
    [OperationContract]
    List<WidgetRecord> List();

    [OperationContract]
    WidgetRecord Get(string Id);

    [OperationContract]
    int Put(string Id, string Desc);
}//end interface

/// <summary>
/// Fake database storage for testing the WCF Data Service
/// </summary>
public static class Database
{
    /// <summary>
    /// Fake database table
    /// </summary>
    public static List<WidgetRecord> WidgetTable = new List<WidgetRecord>() { 
    new WidgetRecord("0001", "red"), 
    new WidgetRecord("0002", "blue") };
}

/// <summary>
/// Implement operations for a service.
/// Representation of a table of widgets identified by scanned barcodes
/// </summary>
[DataContract]
public class WidgetRecord : IScandataService
{
    /// <summary>
    /// Row column: the id which could be a scanned barcode
    /// </summary>
    public string Id { get; set; }

    /// <summary>
    /// Row column: widget description.
    /// (Other columns could be a timestamp, location etc)
    /// </summary>
    public string Desc { get; set; }

    /// <summary>
    /// Dummy initializer, needed for ....(??)
    /// </summary>
    public WidgetRecord()
    {
    return;
    }

    /// <summary>
    /// Initializer to populate the fake database storage.
    /// Creates a new widget record.
    /// </summary>
    /// <param name="Id"></param>
    public WidgetRecord(string Id, string Desc)
    {
    this.Id = Id;
    this.Desc = Desc;
    return;
    }

    /// <summary>
    /// List all stored widgets
    /// </summary>
    /// <returns></returns>
    [OperationContract]
    public List<WidgetRecord> List()
    {
    return Database.WidgetTable;
    }

    /// <summary>
    /// Get info on an existing widget
    /// </summary>
    /// <param name="Id"></param>
    /// <returns></returns>
    [OperationContract]
    public WidgetRecord Get(string Id)
    {
    WidgetRecord sd = Database.WidgetTable.Where(n => n.Id == Id).FirstOrDefault();
    if (sd == null)
        Debug.WriteLine(string.Format("Found: {0} - {1}", sd.Id, sd.Desc));
    else
        Debug.WriteLine(string.Format("Not found: id={0}", Id));
    return sd;
    }

    /// <summary>
    /// Add a new widget to the database
    /// </summary>
    /// <param name="Id"></param>
    /// <param name="Desc"></param>
    /// <returns></returns>
    [OperationContract]
    public int Put(string Id, string Desc)
    {
    Database.WidgetTable.Add(new WidgetRecord(Id, Desc));
    Debug.WriteLine(string.Format("Put: {0} - {1}", Id, Desc));
    return 0;
    }
}//end class

In other sources I often see a partial class for the [DataContract] with field members, and another class with the methods. 在其他资源中,我经常看到带有字段成员的[DataContract]partial class ,以及带有方法的另一个类。 I don't understand why this should be separated. 我不明白为什么要分开。 I am just trying to use the ServiceContract interface as a base class for my data class. 我只是想将ServiceContract接口用作数据类的基类。 Anyway, my class with fields and methods builds OK. 无论如何,我的带有字段和方法的类可以正常构建。

I refer to the above class in the code-behind of WcfDataService.svc , which is App_Code\\WcfDataService.cs : 我在WcfDataService.svccode-behind引用了上述类,即App_Code\\WcfDataService.cs

//using System;
using System.Data.Services;//IDataServiceConfiguration, EntitySetRights, ServiceOperationRights, DataServiceProtocolVersion
//using System.Data.Services.Common;
//using System.Collections.Generic;
//using System.Linq;
//using System.ServiceModel.Web;

public class WcfDataService : DataService<WidgetRecord>
{
    // This method is called only once to initialize service-wide policies.
    public static void InitializeService(IDataServiceConfiguration config)
    {
    // TODO: set rules to indicate which entity sets and service operations are visible, updatable, etc.
    // Examples:
    config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);
    config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
    //config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
    return;
    }
}//end class

This all builds and runs, but basically does nothing, yet. 所有这些都可以构建和运行,但是基本上什么也没做。

http://localhost:56794/website_for_rest/wcfDataService.svc/
-->
<?xml version="1.0" encoding="UTF-8" standalone="true"?>
<service xmlns="http://www.w3.org/2007/app" 
    xmlns:app="http://www.w3.org/2007/app" 
    xmlns:atom="http://www.w3.org/2005/Atom" 
    xml:base="http://localhost:56794/website_for_rest/WcfDataService.svc/">
    <workspace>
        <atom:title>Default</atom:title>
    </workspace>
</service>

I cannot add a command to the URL: 我无法在URL中添加命令:

http://localhost:56794/website_for_rest/wcfDataService.svc/List
-->
page not found

Do I need to add something to the web.config ? 我是否需要在web.config添加一些内容? VS gave me a 126-line web.config and I don't know where to add what. VS给了我一个126行的web.config ,我不知道在哪里添加什么。

Any help is appreciated. 任何帮助表示赞赏。

The answer is, at least for me, that the simplest REST example does not use WCF Data Service, which is a framework to simplify REST. 答案(至少对我而言)是,最简单的REST示例不使用WCF数据服务,后者是简化REST的框架。 However, there is only a need to simplify REST if you have a lot of data and many actions to implement. 但是,如果您有大量数据和要执行的许多操作,则仅需要简化REST。 For a starter, and for simple data transfers, you can do REST without a framework. 首先,为了进行简单的数据传输,您可以在没有框架的情况下进行REST。 And when you need a framework, there is a lot of choice, see eg this list of a few dozen frameworks . 而当您需要一个框架时,有很多选择,例如,请参阅此几十个框架的列表 To begin with, SOAP is one of the older ones, and fallen out of favor because of being too complex. 首先,SOAP是较老的一种,并且由于过于复杂而失宠。 Same with Web Services. 与Web服务相同。 Apparently, WCF Data Service, meant to succeed WS, is in turn replaced by Web API. 显然,WCF数据服务(意在继承WS)将被Web API取代。

The problem with such frameworks is that they might create new problems. 这种框架的问题在于它们可能会产生新的问题。 For me it is a disadvantage that I have to upgrade my tooling, because VS2010 with .Net3.5 does not support Web API. 对我来说,必须升级我的工具是一个缺点,因为带有.Net3.5的VS2010不支持Web API。 Upgrading is a Good Thing, but not if it interferes with a large project I am working on. 升级是一件好事,但是如果它干扰了我正在从事的大型项目,那不是一件好事。 Or WCF Data Services is just not clear to me, has all kinds of smart bindings that I do not grasp, see my question. 还是WCF数据服务对我来说还不清楚,它具有我不掌握的各种智能绑定,请参阅我的问题。 Many examples exist for WCF DS, but are combined with ADO.NET to help you handling lots of tables. WCF DS存在许多示例,但已与ADO.NET结合使用,以帮助您处理大量表。

Staying with the Microsoft environment (VS, .Net, Asp), it is easy to start with plain REST. 与Microsoft环境(VS,.Net,Asp)保持一致,从纯REST开始很容易。 Just create an empty web page, say Default.aspx , and start programming REST functionality in its Page_Load() . 只需创建一个空网页,例如Default.aspx ,然后在其Page_Load()开始编写REST功能。

To see if a GET, PUT, POST etc request has arrived, look at Request.RequestType . 要查看GET,PUT,POST等请求是否已到达,请查看Request.RequestType

To get at the data in the HTTP body: Request.BinaryRead(Request.ContentLength) . 要获取HTTP正文中的数据: Request.BinaryRead(Request.ContentLength)

If you need to handle authorization, get the username and password from the Authentication Http header line with: Request.Params["HTTP_AUTHORIZATION"] , which is base64 encoded. 如果您需要处理授权,请从Authentication Http标头行中获取用户名和密码,并带有: Request.Params["HTTP_AUTHORIZATION"] ,它是base64编码的。 Then you will want a secure connection with HTTPS, which encrypts the entire HTTP packet, including HTTP headers, at the transport (TCP) level. 然后,您将需要与HTTPS进行安全连接,以在传输(TCP)级别对整个HTTP数据包(包括HTTP标头)进行加密。

To return HTTP status codes and/or error messages, just add a regular asp text control to the page. 要返回HTTP状态代码和/或错误消息,只需在页面上添加常规的asp文本控件即可。 It is also possible to replace the entire http response with fiddling with the Response object, if you want to RESTful return a data structure. 如果要RESTful返回数据结构,也可以用Response对象来替换整个http响应。

With the Telerik fiddler tool, it is easy to craft an HTTP packet to test your simple REST server page. 使用Telerik fiddler工具,可以很容易地制作一个HTTP数据包来测试您的简单REST服务器页面。

For clients to reach your page with better URLs you need to use some URL rewriting. 为了使客户可以使用更好的URL访问您的页面,您需要使用一些URL重写。 This involves downloading and installing a rewrite module, and adding rules to your web.config. 这涉及下载和安装重写模块,以及向您的web.config添加规则。 This seems to be a good source with detailed explanations and examples 通过详细的解释和示例,这似乎是一个很好的来源。

Of course using a nice framework would be great, but a barebones implementation is a great way to study REST, and is already a great improvement over older FTP methods of exchanging data as still seen very often in my industry. 当然,使用一个好的框架会很好,但是准系统的实现是研究REST的一种好方法,并且已经比旧的FTP交换数据的方法有了很大的改进,这在我的行业中仍然很常见。

Thanks to Mason, who helped me realize that WCF DS is just one of many frameworks. 感谢Mason,他帮助我意识到WCF DS只是众多框架之一。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM