web-dev-qa-db-ja.com

方法POST XMLをMVCコントローラーに?(キー/値の代わりに)

フィドラーを使用して私は体を渡すことができます

someXml = ThisShouldBeXml

そしてコントローラーで

    [HttpPost]
    public ActionResult Test(object someXml)
    {
        return Json(someXml);
    }

このデータを文字列として取得します

フィドラーにXMLをMVCActionControllerに渡すにはどうすればよいですか?本文の値をrawxmlとして設定しようとすると、機能しません。

ボーナスポイントについては、VBscript/Classic ASPからこれを行うにはどうすればよいですか?

私は現在持っています

DataToSend = "name=JohnSmith"

          Dim xml
         Set xml = server.Createobject("MSXML2.ServerXMLHTTP")
   xml.Open "POST", _
             "http://localhost:1303/Home/Test", _
             False
 xml.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
 xml.send DataToSend
18
punkouter

XMLデータをファイルとしてMVCコントローラーに直接渡すことはできません。最良の方法の1つは、XMLデータをHTTPポスト付きのストリームとして渡すことです。

XMLを投稿する場合、

  1. XMLデータをストリームに変換してHTTPヘッダーに添付する
  2. コンテンツタイプを「text/xml; encoding = 'utf-8'」に設定します

XMLをMVCControllerに投稿する方法の詳細については、 このstackoverflow post を参照してください。

コントローラでXMLを取得するには、次の方法を使用します

[HttpPost] 
public ActionResult Index()
{
    HttpWebResponse response = (HttpWebResponse)request.GetResponse();

    if (response.StatusCode == HttpStatusCode.OK)
    {
        // as XML: deserialize into your own object or parse as you wish
        var responseXml = XDocument.Load(response.GetResponseStream());

        //in responseXml variable you will get the XML data
    }
}
10
Adersh M

これは、XMLをMVCコントローラーに支払う方法のようです

XMLをPOSTとしてASP MVC .NET のActionResultに渡す方法

これをWEBAPIで機能させようとしましたが、できなかったため、代わりにMVC'Controller 'を使用する必要がありました。

3
punkouter

データをMVCで刺し傷として渡すには、プレーンテキストを処理する独自のメディアタイプフォーマッターを作成する必要があります。次に、フォーマッタを設定セクションに追加します。

新しいフォーマッターを使用するには、text/plainのように、そのフォーマッターのContent-Typeを指定します。

テキストのサンプルフォーマッタ

using System;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using System.IO;
using System.Text;

namespace SampleMVC.MediaTypeFormatters
{
    public class TextMediaTypeFormmatter : XmlMediaTypeFormatter
    {
        private const int ByteChunk = 1024;
        private UTF8Encoding StringEncoder = new UTF8Encoding();

        public TextMediaTypeFormmatter()
        {
            base.UseXmlSerializer = true;
            SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/plain"));
        }

        public override bool CanReadType(Type type)
        {
            if (type == typeof(string))
            {
                return true;
            }
            return false;
        }

        public override bool CanWriteType(Type type)
        {
            if (type == typeof(string))
            {
                return true;
            }
            return false;
        }

        public override Task<object> ReadFromStreamAsync(Type type, Stream readStream, System.Net.Http.HttpContent content, IFormatterLogger formatterLogger)
        {
            StringBuilder StringData = new StringBuilder();
            byte[] StringBuffer = new byte[ByteChunk];
            int BytesRead = 0;

            Task<int> BytesReadTask = readStream.ReadAsync(StringBuffer, 0, ByteChunk);
            BytesReadTask.Wait();

            BytesRead = BytesReadTask.Result;
            while (BytesRead != 0)
            {
                StringData.Append(StringEncoder.GetString(StringBuffer, 0, BytesRead));
                BytesReadTask = readStream.ReadAsync(StringBuffer, 0, ByteChunk);
                BytesReadTask.Wait();

                BytesRead = BytesReadTask.Result;
            }

            return Task<object>.Run(() => BuilderToString(StringData));
        }

        private object BuilderToString(StringBuilder StringData)
        {
            return StringData.ToString();
        }

        public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, System.Net.Http.HttpContent content, System.Net.TransportContext transportContext)
        {
            byte[] StringBuffer = StringEncoder.GetBytes((string)value);
            return writeStream.WriteAsync(StringBuffer, 0, StringBuffer.Length);
        }
    }
}

コントローラ方式:

[HttpPost]
public async Task<HttpResponseMessage> UsingString([FromBody]string XmlAsString)
{
    if (XmlAsString == null)
    {
        return this.Request.CreateResponse(HttpStatusCode.BadRequest);
    }

    return this.Request.CreateResponse(HttpStatusCode.OK, new { });
}

WebApiConfig.cs Registerメソッドでのセットアップ:

config.Formatters.Add(new TextMediaTypeFormmatter());

フィドラーヘッダー:

User-Agent: Fiddler
Content-Type: text/plain

MVC Controllerはそのようなリクエスト処理には理想的ではありませんが、それがタスクだったので、それに取り掛かりましょう。私が受け入れるXMLを用意しましょう:

<document>
<id>123456</id>
    <content>This is document that I posted...</content>
    <author>Michał Białecki</author>
    <links>
        <link>2345</link>
        <link>5678</link>
    </links>
</document>

組み込みのパラメーター逆シリアル化を使用していくつかのソリューションを試しましたが、どれも機能していないようで、最後に、メソッド本体で要求を逆シリアル化しました。そのためのヘルパージェネリッククラスを作成しました。

public static class XmlHelper
{
    public static T XmlDeserializeFromString<T>(string objectData)
    {
        var serializer = new XmlSerializer(typeof(T));

        using (var reader = new StringReader(objectData))
        {
            return (T)serializer.Deserialize(reader);
        }
    }
}

DTOをxml属性で装飾しました:

[XmlRoot(ElementName = "document", Namespace = "")]
public class DocumentDto
{
    [XmlElement(DataType = "string", ElementName = "id")]
    public string Id { get; set; }

    [XmlElement(DataType = "string", ElementName = "content")]
    public string Content { get; set; }

    [XmlElement(DataType = "string", ElementName = "author")]
    public string Author { get; set; }

    [XmlElement(ElementName = "links")]
    public LinkDto Links { get; set; }
}

public class LinkDto
{
    [XmlElement(ElementName = "link")]
    public string[] Link { get; set; }
}

そして、そのすべてをコントローラーで使用しました。

public class DocumentsController : Controller
{
    // documents/sendDocument
    [HttpPost]
    public ActionResult SendDocument()
    {
        try
        {
            var requestContent = GetRequestContentAsString();
            var document = XmlHelper.XmlDeserializeFromString<DocumentDto>(requestContent);

            return new HttpStatusCodeResult(HttpStatusCode.OK);
        }
        catch (System.Exception)
        {
            // logging
            return new HttpStatusCodeResult(HttpStatusCode.InternalServerError);
        }
    }

    private string GetRequestContentAsString()
    {
        using (var receiveStream = Request.InputStream)
        {
            using (var readStream = new StreamReader(receiveStream, Encoding.UTF8))
            {
                return readStream.ReadToEnd();
            }
        }
    }
}

これを使用するには、Postmanなどを使用してリクエストを送信するだけです。 POSTリクエストを http://yourdomain.com/documents/sendDocument エンドポイントに送信しています。上記のxml本体を使用します。言及する価値のある詳細の1つはヘッダーです。追加Content-Type:text/xml、または動作要求。

そしてそれは動作します: working deserialization

あなたは私のブログで投稿全体を見ることができます: http://www.michalbialecki.com/2018/04/25/accept-xml-request-in-asp-net-mvc-controller/

0
Mik