【问题标题】:Why am I getting a "NotSupportedException" with this code?为什么我收到此代码的“NotSupportedException”?
【发布时间】:2014-03-07 20:01:28
【问题描述】:

我正在尝试使用以下代码从手持设备(Compact Framework)调用 Web API 方法:

// "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;
        }
    }
}

SendXMLFile() 中的某处,它因“NotSupportedException”而失败...由于它在手持设备上运行,我无法在其中设置断点它并逐步通过它;我可以在整个 (MessageBox.Show()) 中添加一堆调试语句,但我宁愿不这样做。

服务器代码甚至没有到达我在下面的“XDocument doc =”行中设置的断点:

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

是不是因为某种原因,Compact 框架不能调用(RESTful)Web API 方法?显然,客户端(手持式/紧凑型框架)编译并运行,它只是拒绝真正遵循所有的运行时现实。

我的代码是否需要稍作改动才能适应,还是我需要采取完全不同的策略?

【问题讨论】:

  • 尚未审查您的代码,但马上开始...1。为什么你不能通过设备上的代码来学习?我一直这样做。 2. Fiddler 在请求期间在服务器端运行时会告诉你什么?请求是否通过?
  • 如果uri is something like http://localhost:28642/api/ControllerName/PostArgsAndXMLFile?serialNum=8675309&amp;siteNum=42 然后你执行uri = "/" + uri;,这不会产生格式错误的URL吗?
  • @tcarvin: "服务器代码甚至没有到达断点"
  • @tcarvin:“通过设备上的代码steo?我一直这样做”我对此的唯一回应是:“Luck-E!”几个月前,我尝试这样做的辛苦在这个网站上得到了很好的记录,但我从来没有能够做到这一点。我可以在服务器应用程序中设置断点,但不能在手持设备上。
  • 不记得那个特定的线程,但我对无法在设备上进行调试表示哀悼。

标签: asp.net-web-api httpwebrequest compact-framework bytearray streamreader


【解决方案1】:

Web API 将无法处理您的正文内容。您将其声明为 application/x-form-urlencoded,但它实际上是 XML 格式的,并且您的方法签名期望它是一个 XMLDataContract 序列化 string

不要使用参数stringifiedXML,而是只需读取方法中的主体..

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

或者事件更好,直接使用流。

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

这样,您可以将客户端上的 ContentType 按原样放回application/xml

【讨论】:

  • 第一个示例实际上导致之前工作的代码失败。 XDocument doc = XDocument.Load(await Request.Content.ReadAsStreamAsync()); System.Xml.XmlException 未被用户代码处理 HResult=-2146232000 Message=缺少根元素。
  • @B.ClayShannon 这有时可能是因为 UTF 编码中的 BOM 没有得到正确处理。当我尝试使用 WebClient 将 XML 作为字符串下载时,我总是遇到这个问题。
  • 这看起来不错/很有希望,但是客户端代码会是什么样子?未在 REST URL 中引用 XML 是如何发送的?
  • @B.ClayShannon 从技术上讲,您应该将内容类型设置为 appliication/xml,但这不会改变任何内容。您显示的客户端代码应该可以很好地发送文件中的字节。
【解决方案2】:

在服务器端使用 Darrel 的代码(我使用的是第二个,Stream),这适用于客户端:

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;
        }
    }
}

可以这样称呼:

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);
}

【讨论】:

  • 也就是说,这适用于与服务器在同一台机器上运行的测试应用程序;这只是手持代码的“概念验证”,必须“简化”并且不能引用“localhost”(它本身是手持设备,而不是它所连接的 PC)。跨度>
猜你喜欢
  • 1970-01-01
  • 2014-08-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-20
  • 2013-03-05
  • 1970-01-01
相关资源
最近更新 更多