简体   繁体   中英

Am I being too explicit in passing an HttpWebRequest object to a Web API method?

I know (at least I think it's so) that when a Web API method is invoked, an HttpWebRequest is passed to it by the client. IOW, when a client sends something like this to invoke a Web API method:

192.168.125.50:28642/api/DeliveryItems/PostArgsAndXMLFileAsStr?serialNum=42&siteNum=99

...a HttpWebRequest object containing values for serialNum (42) and siteNum (99) are passed to the method.

I also hold (as of now, anyway) that if a large bunch of data needs to be sent (too many/much to pass as part of the URI, as serialNum and siteNum are in the example), this data can be embedded in the HttpWebRequest object on the client like this:

string data = "bla blee bloo blah foo bar doo dah";
WebRequest request = WebRequest.Create(uri);
. . .
byte[] arrData = Encoding.UTF8.GetBytes(data);
request.ContentLength = arrData.Length;
using (Stream oS = request.GetRequestStream())
{
    oS.Write(arrData, 0, arrData.Length);
}
WebResponse response = request.GetResponse();

...and then decoded on the other (server) end using the "[FromBody]" attribute, something like this:

public void PostArgsAndXMLFileAsStr([FromBody] string stringifiedXML, string serialNum, string siteNum)
{
    XDocument doc = XDocument.Parse(stringifiedXML);

Are my assumptions correct? IOW, for test code like this:

[Test]
public void TestNRBQDeliveryItemInterfacePostPPTData()
{
    var DeliveryItem = IOC.container.Resolve<INRBQDeliveryItem>();

    string data = @"<Command>
    <DSD>
    <line_id>1</line_id>
       . . .
    <discount>0.25</discount>
    <fileDate>12/19/2013 1:33:27 PM</fileDate>
    </DSD>
    </Command>";
    string uri = "http://localhost:21609/api/deliveryitems/InsertIntoPPTData";
    WebRequest request = WebRequest.Create(uri);
    request.Method = Enum.ToObject(typeof(HttpMethods), HttpMethods.POST).ToString();
    request.ContentType = "application/json";
    ((HttpWebRequest)request).Accept = request.ContentType;
    ((HttpWebRequest)request).KeepAlive = false;
    ((HttpWebRequest)request).ProtocolVersion = HttpVersion.Version10;

    Encoding encoding = Encoding.UTF8; // needed?
    byte[] arrData = Encoding.UTF8.GetBytes(data);
    request.ContentLength = arrData.Length;
    using (Stream oS = request.GetRequestStream())
    {
        oS.Write(arrData, 0, arrData.Length);
    }
    // Send the request to the server by calling GetResponse. (http://msdn.microsoft.com/en-us/library/debx8sh9(v=vs.110).aspx)
    WebResponse response = request.GetResponse();
    Assert.IsNotNull(response);
}

...should my current Web API method:

[HttpPost]
[Route("api/deliveryitems/InsertIntoPT109Data")] 
public void InsertIntoPT109Data(HttpWebRequest httpwebreq)
{
    HHSService.InsertIntoPPTData(httpwebreq); 
}

...instead be changed to:

[HttpPost]
[Route("api/deliveryitems/InsertIntoPT109Data")]
public void InsertIntoPT109Data([FromBody] stringifiedXML)
{
    HHSService.InsertIntoPT109Data(stringifiedXML);
}

?

In an attempt to be more plain, I think that I am being too explicit by using an HttpWebRequest object as an argument to my Web API method; I think/hope that a HttpWebRequest being sent is "a given" and what I need in this case is the "[FromBody] stringifiedXML" argument, and that I can then "unpack" the [FromBody] data something like the example I gave above (eg, "XDocument doc = XDocument.Parse(stringifiedXML);").

Am I correct in either my existing code (which explicitly passes a HttpWebRequest object as the method's arg) or in the other case (where I assume a HttpWebRequest object is implicitly known to be there, and instead deal with the [FromBody] data embedded within it), or am I right in neither case?

If I am right in the first/current case (that I must pass a HttpWebRequest object), how can I get at the embedded data in the HttpWebRequest object? Would I need to call "getResponseStream" or...???

UPDATE

If I'm able to forego the explicit usage of HttpWebRequest, there's another wrinkle. This:

void InsertIntoPT109Data([FromBody] stringifiedXML);

...doesn't compile as an interface method, because the "[FromBody]" attribute is not recognized. Would replacing that with "String" suffice?

UPDATE 2

I've replaced the "HttpWebRequest httpwebreq"s with "[FromBody] String stringifiedXML", such as:

public void InsertIntoPT109Data([FromBody] String stringifiedXML)

...but now I get, "The type or namespace name 'FromBody' could not be found (are you missing a using directive or an assembly reference?)"

I get this whether I have added "using System.Web.Http;" or not.

If I need to add a DLL to the project references, which DLL is it?

The HttpWebRequest / HttpWebResponse are not sent to or received from the server. They are used to send to and receive data from the server.

Your assumptions are incorrect.

I think @paulo-morgado covered the first part well, nothing further for me to add.

Regarding your FromBody update at the end of your post, two things to note:

  1. you need to give a type to stringifiedXML (I assume string ) even if you use [FromBody] , and
  2. you need to add:
    using System.Web.Http;
    at the top of your file before you can use [FromBody] . Sometimes people confuse that with "System.Web.Mvc" which is specific to MVC projects and not Web API.

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