开发者

Design practice for REST API into existing .NET C# website

开发者 https://www.devze.com 2023-03-23 09:10 出处:网络
I\'d like to have our user landing web-server POST XML to our computation web server (to crunch over the XML data). The landing and computing web-servers are only connected via the internet - so it se

I'd like to have our user landing web-server POST XML to our computation web server (to crunch over the XML data). The landing and computing web-servers are only connected via the internet - so it seems best to have a REST API on the computing web-server so the XML data can POSTed for processing.

To be honest, we're all SW engineers but our competency is in the alg开发者_开发问答orithmic processing, not the web plumbing or ASP.NET itself. I looked around and saw WCF (Windows Communication Foundation) being kicked around quite a bit. I'm concerned WCF might be too complex/over engineered for our situation.

So, what is the simplest way for me to enable the existing web-forms based processing website to accept POSTed XML? I guess I need to register a URI (in web.config?) as the API interface, have a handler on that URI and retrieve the XML string - I just don't know the implementational steps :(. So a toy example or a pointer to a tutorial would be awesome!

BTW, once I have the XML string on the processing server, I'm golden!

Thanks Sid


If you merely want the thinnest possible layer, without messing with the plumbing or figuring out wcf, create an asp.net web project then right click and add item choose an httphandler and in the event it gives pull the xml string from response.items[strings key]. post it as the url of the ashx?key=your xml string


Ok, so I read up several documents to be able to answer my own question. Basically WCF REST has been changing quite a bit. It's quite complicated in the setup in earlier versions but in recent versions (.NET 4 and WCF REST starter kit) the overhead of configuration is a lot less.

To get WCF REST running quickly, I basically did 3 things.

  1. Setup the path to the service in global.asax.cs (I had to manually add/edit this as global.asax and global.asax.cs)
  2. Setup the "service contract" (i.e. "doThisMethod" inside http://localhost/doThisMethod/ )
  3. Setup the "data contract" (i.e. if you're POSTing any XML/JSON via the HTTP body, this "maps"/serializes between XML/JSON and the native C# objects.)

For very basic REST APIs (i.e. only HTTP GET) just the first two steps are sufficient. Please note, I scrubbed out some stuff during copy-pasting, but you should get the idea ...

Step1a

global.asax

<%@ Application Codebehind="~/App_Code/Global.asax.cs" Inherits="MyBLL.Global" Language="C#" %>

Step1b

global.asax.cs

using System;
using System.Collections.Generic;
using System.ServiceModel.Activation;
using System.Web;
using System.Web.Routing;

public class Global : System.Web.HttpApplication
{
    void Application_Start(object sender, EventArgs e)
    {
        // Code that runs on application startup
        RouteTable.Routes.Add(new ServiceRoute("/", new WebServiceHostFactory(), typeof(TestService)));
    }
}

Step2a

As you can see, I split the interface (abstract class) and the actual implementation into two separate files for clean separation.

TestInterface.cs

using System;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;

[ServiceContract]
interface TestInterface
{
    [OperationContract]
    string TestAsXML(string extra);

    [OperationContract]
    string TestAsJSON(string extra);
}

Step2b TestService.cs

using System;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class TestService : TestInterface

    [WebInvoke(UriTemplate = "Test/{username}", Method = "GET", ResponseFormat = WebMessageFormat.Xml)]
    public string TestAsXML(string username)
    {
        WebOperationContext.Current.OutgoingResponse.ContentType = "text/xml";
        return String.Format("Hello {0}!", String.IsNullOrWhiteSpace(username) ? "world" : username);
    }

    [WebInvoke(UriTemplate = "Test/{username}?format=json", Method = "GET", ResponseFormat = WebMessageFormat.Json)]
    public string TestAsJSON(string username)
    {
        // NOTE, if we GET this from a browsers, it will most likely have 
        // "Accept: text/html, application/xhtml+xml, */*" in the HTTP header
        // So the framework will return XML instead. Try from Fiddler2 instead or
        // write your own WCF client or from AJAX
        WebOperationContext.Current.OutgoingResponse.ContentType = "application/json";
        return String.Format("Hello {0}!", String.IsNullOrWhiteSpace(username) ? "world" : username);
    }

Step3

For the "test" example above, everything is over the URI itself (due to GET), so you don't need the stuff below. Practically, once you want to use POST etc, you'll need to send the object in the HTTP body. When exchanging Data, use a "Data Contract" to leverage WCF's features as below.

Here I'll be sending one class in the HTTP body, which in turn has one string and one int within.

TestInput.cs

using System;
using System.Web;
using System.Runtime.Serialization;

// "" needed to clear out ugly xmlns namespace tags to make it plain old XML (POX)
// If you want them, ether take it out or specify on your own
[DataContract(Name = "TestInput", Namespace = "")] 
public class TestInput
{
    // NOTE: If Order property is skipped, the data will be serialized 
    // alphabetically per variable names!!
    // This can kill services, so better to be explicit
    [DataMember(Order = 0)] 
    int SomeNumber;

    // NOTE: If Name property is used XML will have UserName instead of internalUserName
    [DataMember(Name="UserName", Order = 1)] 
    string internalUserName;       
}
0

精彩评论

暂无评论...
验证码 换一张
取 消