我从存储过程中获取XML输出。我想要做的是获取XML并通过ASP.NET传递出来:
UnitOfWork
但我一直收到这些错误:
public XmlDocument GetPunchListXml(string communityDesc)
{
try
{
using (connection = new SqlConnection(connectionString))
{
connection.Open();
using (SqlCommand command = new SqlCommand("GetPunchList", connection))
{
command.CommandType = CommandType.StoredProcedure;
SqlParameter parameter1 = new SqlParameter("@communityDesc", SqlDbType.VarChar);
parameter1.Value = communityDesc;
parameter1.Direction = ParameterDirection.Input;
command.Parameters.Add(parameter1);
var doc = new XmlDocument();
var reader = command.ExecuteXmlReader();
if (reader.Read())
{
doc.Load(reader);
}
return doc;
}
}
}
finally
{
connection.Close();
}
}
我做错了什么?我试图获取XML的方式是否有问题,或者是XML本身的问题?
我尝试了以下内容:
<Error>
<Message>An error has occurred.</Message>
<ExceptionMessage>
The 'ObjectContent`1' type failed to serialize the response body for content type 'application/xml; charset=utf-8'.
</ExceptionMessage>
<ExceptionType>System.InvalidOperationException</ExceptionType>
<StackTrace/>
<InnerException>
<Message>An error has occurred.</Message>
<ExceptionMessage>
Type 'System.Xml.XmlDocument' is an invalid collection type since it does not have a valid Add method with parameter of type 'System.Object'.
</ExceptionMessage>
<ExceptionType>
System.Runtime.Serialization.InvalidDataContractException
</ExceptionType>
<StackTrace>
at System.Runtime.Serialization.DataContract.DataContractCriticalHelper.ThrowInvalidDataContractException(String message, Type type)
at WriteArrayOfanyTypeToXml(XmlWriterDelegator , Object , XmlObjectSerializerWriteContext , CollectionDataContract )
at System.Runtime.Serialization.CollectionDataContract.WriteXmlValue(XmlWriterDelegator xmlWriter, Object obj, XmlObjectSerializerWriteContext context)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.WriteDataContractValue(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithoutXsiType(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle)
at System.Runtime.Serialization.DataContractSerializer.InternalWriteObjectContent(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver)
at System.Runtime.Serialization.DataContractSerializer.InternalWriteObject(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver)
at System.Runtime.Serialization.XmlObjectSerializer.WriteObjectHandleExceptions(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver)
at System.Runtime.Serialization.DataContractSerializer.WriteObject(XmlWriter writer, Object graph)
at System.Net.Http.Formatting.XmlMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, HttpContent content)
at System.Net.Http.Formatting.XmlMediaTypeFormatter.WriteToStreamAsync(Type type, Object value, Stream writeStream, HttpContent content, TransportContext transportContext, CancellationToken cancellationToken)
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at System.Web.Http.WebHost.HttpControllerHandler.<WriteBufferedResponseContentAsync>d__1b.MoveNext()
</StackTrace>
</InnerException>
</Error>
并且遇到了这些错误:
var doc = new XmlDocument();
string s = "";
using (XmlReader reader = command.ExecuteXmlReader())
{
while (reader.Read())
{
//doc.Load(reader);
s = reader.ReadOuterXml();
doc.LoadXml(s);
}
}
return doc;
答案 0 :(得分:7)
问题可能在于您使用XmlDocument
的结果,因为我也找不到代码的任何问题。至于为什么我相信这个
HttpControllerHandler
开始的例外情况,因此可能与您提供回复的位置或方式有关。InvalidOperationException
,但它会认为这只会在The SqlConnection closed or dropped during a streaming operation. For more information about streaming, see SqlClient Streaming Support.
XmlException
,因此根据您收到的异常情况,这不是一个可能的失败点。这是猜测,因为我不知道您正在使用什么框架,或者这是WebApi方法还是在调用堆栈中向下提供结果的方法。
因此,您需要解决的问题是将数据转换为可以通过您使用的任何框架进行序列化的格式。如需更多帮助,请提供。
WebApiConfig.cs
文件中配置了正确的格式化程序。 GlobalConfiguration.Configuration.Formatters.Add(new System.Net.Http.Formatting.XmlMediaTypeFormatter()); GlobalConfiguration.Configuration.Formatters.XmlFormatter.UseXmlSerializer = true;
我可以通过在Web API控制器中返回XmlDocument
作为响应来复制确切的错误和消息。然后再次说明它与方法的内容无关,但更多的是响应中使用的XmlDocument。如果您直接在响应中返回XmlDocument(因此不是较大对象的一部分),我可以通过添加一个知道如何反序列化(提取实际Xml内容)的新HttpContent
类型来修复它{ {1}}。这是基于XmlDocument
发布的上一个SO answer。这是一个完整的自包含示例中的修复。
Darrel Miller
您的方法确实存在一些问题,因为它与using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using System.Web.Http;
using System.Xml;
namespace WebApiTests.Controllers
{
public class HomeController : ApiController
{
const string sampleData = "<?xml version=\"1.0\"?><catalog><book id=\"bk101\"><author>Gambardella, Matthew</author><title>XML Developer's Guide</title><genre>Computer</genre><price>44.95</price><publish_date>2000-10-01</publish_date><description>An in-depth look at creating applications with XML.</description></book></catalog>";
public HttpResponseMessage Get()
{
var doc = new XmlDocument();
doc.LoadXml(sampleData);
return new HttpResponseMessage()
{
RequestMessage = Request,
Content = new XmlContent(doc)
};
}
}
public class XmlContent : HttpContent
{
private readonly MemoryStream _Stream = new MemoryStream();
public XmlContent(XmlDocument document)
{
document.Save(_Stream);
_Stream.Position = 0;
Headers.ContentType = new MediaTypeHeaderValue("application/xml");
}
protected override Task SerializeToStreamAsync(Stream stream, System.Net.TransportContext context)
{
_Stream.CopyTo(stream);
var tcs = new TaskCompletionSource<object>();
tcs.SetResult(null);
return tcs.Task;
}
protected override bool TryComputeLength(out long length)
{
length = _Stream.Length;
return true;
}
protected override void Dispose(bool disposing)
{
if(_Stream != null)
_Stream.Dispose();
}
}
}
有关。以下是带有解释的清理代码。
SqlConnection
答案 1 :(得分:0)
更改以下代码,
var doc = new XmlDocument();
var reader = command.ExecuteXmlReader();
if (reader.Read())
{
doc.Load(reader);
}
如下所示,
XmlDocument doc = new XmlDocument();
XmlReader reader = command.ExecuteXmlReader();
if (reader.Read())
{
doc.Load(reader);
}
如果仍然无效,请分享您从SP返回的xml。
答案 2 :(得分:0)
XmlDocument不可序列化,而是返回XML的字符串表示
using (var stringWriter = new StringWriter())
using (var xmlTextWriter = XmlWriter.Create(stringWriter))
{
xmlDoc.WriteTo(xmlTextWriter);
xmlTextWriter.Flush();
return stringWriter.GetStringBuilder().ToString();
}
答案 3 :(得分:0)
您可以在MediaTypeFormatter
中创建自己的简单ASP.NET Web API
,直接将XmlDocument
流式传输到回复。本回答的最后是一个示例实现。
使用VS向导创建新项目时,在自动生成的public static void Register(HttpConfiguration config)
类的WebApiConfig
方法中注册它。
// This custom media type converter must be inserted before the default media type converter that handles application/xml, do not use config.Formatters.Add(...
config.Formatters.Insert(0, new MediaTypeFormatters.XmlDocumentMediaTypeFormatter());
在控制器类方法中执行与此类似的操作
private HttpResponseMessage Get()
{
XmlDocument doc = new XmlDocument();
XmlDeclaration dec = doc.CreateXmlDeclaration("1.0", "utf-8", null);
doc.AppendChild(dec);
XmlElement rootElement = doc.CreateElement("user");
doc.AppendChild(rootElement);
rootElement.SetAttribute("id", "1");
var response = Request.CreateResponse(HttpStatusCode.OK, doc, "application/xml");
return (response);
}
自定义MediaTypeFormatter示例,以将XmlDocument
流式传输到响应。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
using System.Net;
using System.Xml;
namespace Take5.MediaTypeFormatters
{
public class XmlDocumentMediaTypeFormatter : MediaTypeFormatter
{
private static Type _supportedType = typeof(XmlDocument);
public XmlDocumentMediaTypeFormatter()
{
SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/xml"));
}
public override bool CanReadType(Type type)
{
return type == _supportedType;
}
public override bool CanWriteType(Type type)
{
return type == _supportedType;
}
public override Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
{
var taskSource = new TaskCompletionSource<object>();
try
{
System.Diagnostics.Debug.Assert(false, "Not fully implemented, get doc to read from readStream.");
var doc = new XmlDocument();
taskSource.SetResult(doc);
}
catch (Exception e)
{
taskSource.SetException(e);
}
return taskSource.Task;
}
public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext)
{
var taskSource = new TaskCompletionSource<object>();
try
{
XmlDocument doc = (XmlDocument)value;
XmlWriter writer = XmlWriter.Create(writeStream, new XmlWriterSettings() { Indent = true });
doc.WriteContentTo(writer);
writer.Flush();
taskSource.SetResult(null);
}
catch (Exception e)
{
taskSource.SetException(e);
}
return taskSource.Task;
}
}
}