I am trying to call a Web API method from a handheld device (Compact Framework) with this code:

// "fullFilePath" is a value such as "\Program Files\Bla\abc.xml"
// "uri" is something like "http://localhost:28642/api/ControllerName/PostArgsAndXMLFile?serialNum=8675309&siteNum=42"
SendXMLFile(fullFilePath, uri, 500);
. . .
public static string SendXMLFile(string xmlFilepath, string uri, int timeout) 
{
    uri = uri.Replace('\\', '/');
    if (!uri.StartsWith("/"))
    {
        uri = "/" + uri;
    }
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);

    request.KeepAlive = false;
    request.ProtocolVersion = HttpVersion.Version10;

    request.Method = "POST";

    StringBuilder sb = new StringBuilder();
    using (StreamReader sr = new StreamReader(xmlFilepath))
    {
        String line;
        while ((line = sr.ReadLine()) != null)
        {
            sb.AppendLine(line);
        }
        byte[] postBytes = Encoding.UTF8.GetBytes(sb.ToString());

        if (timeout < 0)
        {
            request.ReadWriteTimeout = timeout;
            request.Timeout = timeout;
        }

        request.ContentLength = postBytes.Length;
        request.KeepAlive = false;

        request.ContentType = "application/x-www-form-urlencoded"; // not "text/xml" correct?

        try
        {
            Stream requestStream = request.GetRequestStream();

            requestStream.Write(postBytes, 0, postBytes.Length);
            requestStream.Close();

            using (var response = (HttpWebResponse)request.GetResponse())
            {
                return response.ToString();
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
            request.Abort();
            return string.Empty;
        }
    }
}

Somewhere in SendXMLFile(), it is failing with "NotSupportedException" though... As it's running on a handheld device, I can't put a breakpoint in it and step through it; I could sprinkle a bunch of debug statements throughout (MessageBox.Show()), but I'd rather not do that.

The server code never even reaches the breakpoint I put on the "XDocument doc =" line below:

[Route("api/ControllerName/PostArgsAndXMLFile")]
public void PostArgsAndFile([FromBody] string stringifiedXML, string serialNum, string siteNum)
{
    XDocument doc = XDocument.Parse(stringifiedXML); 

Is it that the Compact framework can't call a (RESTful) Web API method for some reason? Obviously, the client (handheld/Compact Framework) compiles and runs, it just refuses to actually follow through with the runtime realities of it all.

Does my code require a small alteration for it to fit, or do I need to take a completely different tack?

有帮助吗?

解决方案

Web API is not going to be able to handle your body content. You declared it as application/x-form-urlencoded, but it is actually XML formatted and your method signature is expecting it to be a XMLDataContract serialized string.

Instead of using the parameter stringifiedXML, instead, just read the body inside your method..

[Route("api/ControllerName/PostArgsAndXMLFile")]
public async void PostArgsAndFile(string serialNum, string siteNum)
{
    XDocument doc = XDocument.Parse(await Request.Content.ReadAsStringAsync()); 
}

Or event better, use a stream directly.

[Route("api/ControllerName/PostArgsAndXMLFile")]
public async void PostArgsAndFile(string serialNum, string siteNum)
{
    XDocument doc = XDocument.Load(await Request.Content.ReadAsStreamAsync()); 
}

This way, you can put the ContentType on the client back to application/xml as it should be.

其他提示

Using Darrel's code on the server side (I'm using the second one, the Stream), this works on the Client side:

public static string SendXMLFile(string xmlFilepath, string uri, int timeout)
{
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);

    request.KeepAlive = false;
    request.ProtocolVersion = HttpVersion.Version10;
    request.ContentType = "application/xml";
    request.Method = "POST";

    StringBuilder sb = new StringBuilder();
    using (StreamReader sr = new StreamReader(xmlFilepath))
    {
        String line;
        while ((line = sr.ReadLine()) != null)
        {
            sb.AppendLine(line);
        }
        byte[] postBytes = Encoding.UTF8.GetBytes(sb.ToString());

        if (timeout < 0)
        {
            request.ReadWriteTimeout = timeout;
            request.Timeout = timeout;
        }

        request.ContentLength = postBytes.Length;
        request.KeepAlive = false;

        request.ContentType = "application/x-www-form-urlencoded";

        try
        {
            Stream requestStream = request.GetRequestStream();

            requestStream.Write(postBytes, 0, postBytes.Length);
            requestStream.Close();

            using (var response = (HttpWebResponse)request.GetResponse())
            {
                return response.ToString();
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
            request.Abort();
            return string.Empty;
        }
    }
}

Which can be called like so:

private void buttonNose_Click(object sender, EventArgs e)
{
    String fullFilePath = @"C:\McMurtry\LonesomeDove.XML";
    String uri = @"http://localhost:21608/api/inventory/sendxml/ff/gg/42";
    SendXMLFile(fullFilePath, uri, 500);
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top