简体   繁体   中英

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). 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. 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. This is 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. 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. 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 :

//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:

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

Do I need to add something to the web.config ? VS gave me a 126-line web.config and I don't know where to add what.

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. However, there is only a need to simplify REST if you have a lot of data and many actions to implement. For a starter, and for simple data transfers, you can do REST without a framework. 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. Same with Web Services. Apparently, WCF Data Service, meant to succeed WS, is in turn replaced by 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. 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. Many examples exist for WCF DS, but are combined with ADO.NET to help you handling lots of tables.

Staying with the Microsoft environment (VS, .Net, Asp), it is easy to start with plain REST. Just create an empty web page, say Default.aspx , and start programming REST functionality in its Page_Load() .

To see if a GET, PUT, POST etc request has arrived, look at Request.RequestType .

To get at the data in the HTTP body: 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. Then you will want a secure connection with HTTPS, which encrypts the entire HTTP packet, including HTTP headers, at the transport (TCP) level.

To return HTTP status codes and/or error messages, just add a regular asp text control to the page. 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.

With the Telerik fiddler tool, it is easy to craft an HTTP packet to test your simple REST server page.

For clients to reach your page with better URLs you need to use some URL rewriting. This involves downloading and installing a rewrite module, and adding rules to your 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.

Thanks to Mason, who helped me realize that WCF DS is just one of many frameworks.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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