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.