Я использую asp.net mvc в качестве моего html-сайта (механизм просмотра по умолчанию) и конечной точки сервиса. Конечная точка службы используется моими клиентами WPF и Silverlight путем введения «content-type = text / xml» в заголовок запроса WebClient (см. post от ScottGu по использованию службы в SL, которая вдохновила этот подход) , Я нашел где-то в сети некоторый код, который переопределяет событие OnActionExecuted, например:
public class JsonOrXml : ActionFilterAttribute
{
private static UTF8Encoding UTF8 = new UTF8Encoding(false);
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
// setup the request, view and data
HttpRequestBase request = filterContext.RequestContext.HttpContext.Request;
ViewResult view = (ViewResult)(filterContext.Result);
var data = view.ViewData.Model;
String contentType = request.ContentType ?? string.Empty;
// JSON
if (contentType.Contains("application/json") || (string)view.ViewData["FORMAT"] == "json")
{
filterContext.Result = new JsonResult
{
Data = data
};
}
// POX
else if (contentType.Contains("text/xml") || (string)view.ViewData["FORMAT"] == "xml")
{
// MemoryStream to encapsulate as UTF-8 (default UTF-16)
// http://stackoverflow.com/questions/427725/
//
// MemoryStream also used for atomicity but not here
// http://stackoverflow.com/questions/486843/
//using (MemoryStream stream = new MemoryStream(500))
//{
// using (var xmlWriter =
// XmlTextWriter.Create(stream,
// new XmlWriterSettings()
// {
// OmitXmlDeclaration = false,
// Encoding = UTF8,
// Indent = true
// }))
// {
// new XmlSerializer(data.GetType()).Serialize(xmlWriter, data);
// }
// filterContext.Result = new ContentResult
// {
// ContentType = "text/xml",
// Content = UTF8.GetString(stream.ToArray()),
// ContentEncoding = UTF8
// };
//}
XmlDeclaration xmlDecl = new XmlDocument().CreateXmlDeclaration("1.0", "UTF-8", "yes");
filterContext.Result = new ContentResult
{
ContentType = "text/xml",
Content = xmlDecl.OuterXml + data.ToString(),
ContentEncoding = UTF8
};
}
}
}
Итак, закомментированный фрагмент - это код, который я нашел - посмотрите ссылки на stackoverflow, где я его получил:)
Я переопределил метод ToString () на всех своих бизнес-объектах, чтобы вернуть строку, представляющую, как бизнес-объект хотел бы представить себя в виде xml. WCF выполняет это с помощью атрибутов, но я хотел более чистое решение, которое не основывалось на рефлексии. И я не хотел иметь и проект веб-сайта, и проект WCF - проблема с двумя проектами заключалась в том, что было трудно сохранить их оба синхронно с функциональностью - я получаю запросы типа «почему сервис не позволяет мне фильтровать результаты, как на сайте?»
Меня очень интересуют отзывы других об этом подходе:)
Вот пример бизнес-объекта:
public class ContentFile : Entity
{
public ContentBook BelongsToBook { get; set; }
public string FileName { get; set; }
public XElement FileXml { get; set; }
public Binary FileData { get; set; }
public List<ContentFile> Versions { get; set; }
public List<ContentNode> ContentNodes { get; set; }
public override string ToString()
{
return this.ToString(SaveOptions.DisableFormatting);
}
public string ToString(SaveOptions options)
{
XElement xml = XElement.Parse("<contentFile id=\"" + Id.ToString() + "" + "\" />");
xml.Add(new XElement("fileName", FileName));
xml.Add(new XElement("fileStructure", FileXml));
xml.Add(base.ToString(options));
return xml.ToString(options);
}
}