2017-12-12 6 views
0

ViewModelをシリアル化し、リモートのサードパーティ製のサーバーにデータ処理用に送信しようとしているASP.NET MVC 5アプリケーションがあります。私は何が間違っているのか正確にはわかりませんが、以下は私が試したコードです。ViewModelをXMLにシリアル化してリモートサーバーに送信するにはどうすればよいですか?

はまず、ここで私はViewModelにをシリアル化し、リモートサーバーに送信しようとしていた中で、私のコントローラでPOST方法です:

[HttpPost] 
     public ActionResult Index(Transmission t) 
     { 
      ViewBag.ErrorMessage = ""; 
      ViewBag.OtherMessage = ""; 

      try 
      { 
       //serialize the ViewModel 
       XmlResult xrs = new XmlResult(t); 
       XDocument xdoc = XDocument.Parse(xrs.ToString()); 
       Stream stream = new MemoryStream(); //the memory stream to be used to save the xdoc 
       XmlActionResult xar = new XmlActionResult(xdoc); 
       xdoc.Save(stream); 
       //xrs.ExecuteResult(ControllerContext); 

       //POST the data to the external URL 
       var url = "theUrl"; 
       var PostData = xar; 


       var Req = (HttpWebRequest)WebRequest.Create(url); 
       Req.ContentType = "application/xml"; 
       Req.Method = "POST"; 
       Req.Timeout = 60000; 
       Req.KeepAlive = false; 


       //build the string to send 
       StringBuilder sb = new StringBuilder(); 

       using(StreamReader sr = new StreamReader(stream)) 
       { 
        string line; 
        while((line = sr.ReadLine()) != null) 
        { 
         sb.AppendLine(line); 
        } 
        byte[] postBytes = Encoding.ASCII.GetBytes(sb.ToString()); 
        Req.ContentLength = postBytes.Length; 


        using (Stream requestStream = Req.GetRequestStream()) 
        { 
         requestStream.Write(postBytes, 0, postBytes.Length); 
         requestStream.Close(); 
        } 

        using (var response = (HttpWebResponse)Req.GetResponse()) 
        { 
         ViewBag.OtherMessage = response.ToString(); 
         return View("Error"); //TODO: change this to success when I get the 500 error fixed 
        } 
       } 

      } 
      catch (Exception ex) 
      { 
       string message = ex.Message; 
       ViewBag.ErrorMessage = ex.Message; 
       return View("Error"); 
      } 
     } 
    } 

あなたが上見ることができるように、私は2つのクラスを使用しています、それぞれXmlActionResultXmlResultと呼ばれます。 XmlResultクラスは、ViewModelのシリアル化に使用されています。ここXmlResultクラスの実装です:

public class XmlResult : ActionResult 
    { 
     private object objectToSerialize; 

     /// <summary> 
     /// Initializes a new instance of the <see cref="XmlResult"/> class. 
     /// </summary> 
     /// <param name="objectToSerialize">The object to serialize to XML.</param> 
     public XmlResult(object objectToSerialize) 
     { 
      this.objectToSerialize = objectToSerialize; 
     } 

     /// <summary> 
     /// Gets the object to be serialized to XML. 
     /// </summary> 
     public object ObjectToSerialize 
     { 
      get { return objectToSerialize; } 
     } 

     /// <summary> 
     /// Serializes the object that was passed into the constructor to XML and writes the corresponding XML to the result stream. 
     /// </summary> 
     /// <param name="context">The controller context for the current request.</param> 
     public override void ExecuteResult(ControllerContext context) 
     { 
      if (objectToSerialize != null) 
      { 
       context.HttpContext.Response.Clear(); 
       var xs = new System.Xml.Serialization.XmlSerializer(objectToSerialize.GetType()); 
       context.HttpContext.Response.ContentType = "xml"; 
       xs.Serialize(context.HttpContext.Response.Output, objectToSerialize); 
      } 
     } 
    } 

XmlResultクラスはViewModelにシリアル化した後、私はXmlActionResultクラスを使用してXDocumentを作成しようとしています。ここXmlActionResultクラスの実装です:

public sealed class XmlActionResult : ActionResult 
    { 
     private readonly XDocument _document; 

     public Formatting Formatting { get; set; } 
     public string MimeType { get; set; } 

     public XmlActionResult(XDocument document) 
     { 
      if (document == null) 
       throw new ArgumentNullException("document"); 

      _document = document; 

      // Default values 
      MimeType = "text/xml"; 
      Formatting = Formatting.None; 
     } 

     public override void ExecuteResult(ControllerContext context) 
     { 
      context.HttpContext.Response.Clear(); 
      context.HttpContext.Response.ContentType = MimeType; 

      using (var writer = new XmlTextWriter(context.HttpContext.Response.OutputStream, Encoding.UTF8) { Formatting = Formatting }) 
       _document.WriteTo(writer); 
     } 
    } 

私は私の最初の問題はどこにあるか、これがあると信じています。シリアライズされたViewModelオブジェクトtからXmlResultクラスを使用してXDocumentを作成しますが、 "ルートレベルのデータが無効です。ライン1、ポジション1"というエラーが表示されます。 XDocumentクラスでシリアル化されたViewModelオブジェクトの解析に問題があることを示します。私はここで何をやったのですか?

次に、MemoryStreamXDocument(正常に作成された後)を保存しようとしています。考え方は、StreamReaderを介してMemoryStreamに保存されたXDocumentにアクセスしているStringBuilderオブジェクトからbyteアレイを構築し、HttpWebRequestオブジェクトを介してリモートサーバーに送信することです。しかし、私は上記のエラーのおかげで、まだこれを得ていません。

ご協力いただきまして誠にありがとうございます。私が必要とするならば、私はこの全体のアプローチを変えたいと思っています。私は最初の部分が働いても後者の部分がうまくいくとは確信していないので、どんなアドバイスも耳を傾けます。ありがとうございました。

アップデート:例外の詳細について

例外は、このラインで投げている:

XDocument xdoc = XDocument.Parse(xrs.ToString()); 

innerExceptionはnullです。 Messageは、 "ルートレベルのデータが無効です。ライン1、ポジション1"です。

+0

*ルートレベルのデータは無効です。 1行1位* - 例外の型、メッセージ、トレースバック、内部例外を含む例外の完全な 'ToString()'出力を共有できますか?どの列に例外がスローされますか?あなたはあなたの質問を[mcve]に還元できますか? – dbc

+0

@dbc待って。 – ic3man7019

+0

@dbc例外に関する詳細情報が提供されています。 – ic3man7019

答えて

1
public async Task<ActionResult> Index(Transmission t) 
    { 
     ViewBag.ErrorMessage = ""; 
     ViewBag.OtherMessage = ""; 

     try 
     { 

      var xmlSerializer = new XmlSerializer(typeof(Transmission)); 
      using (StringWriter sw = new StringWriter()) 
      { 
       xmlSerializer.Serialize(sw, t); 
       var contentData = sw.ToString(); 
       var httpContent = new StringContent(contentData, Encoding.UTF8, "application/xml"); 
       var httpClient = new HttpClient(); 
       httpClient.Timeout = new TimeSpan(0, 1, 0); 
       var response = await httpClient.PostAsync("", httpContent); 
       ViewBag.OtherMessage = await response.Content.ReadAsStringAsync(); 
       return View("Error"); //TODO: change this to success when I get the 500 error fixed 
      } 
     } 
     catch (Exception ex) 
     { 
      string message = ex.Message; 
      ViewBag.ErrorMessage = ex.Message; 
      return View("Error"); 
     } 
    } 
+0

これは正しい解決策です。私は、XMLエンコーディングがXMLデータに現れないようにいくつかの変更を加えなければなりませんでしたが、これは正しいです。ありがとうございました。これは非常に役に立ちます。 – ic3man7019

+0

@Franが正しかった。私はXmlSerializerが私のためにやることをたくさん行っていました。私は 'XmlResult'と' XmlActionResult'クラスが何をしているのか誤解しました。私はそれらをまったく必要としないことが判明しました。 – ic3man7019

関連する問題