在我的MVC Web应用程序中,我开发了一个函数来返回Newsstand Atom Feed(用于Apple的报亭)。 他们对此Feed的要求之一是它有效地以UTF-8编码,并且不得包含BOM。 这就是我编写视图的方式(类名是虚构的,以保护我公司的隐私):
<%@ Page Language="VB" Inherits="System.Web.Mvc.ViewPage(Of IEnumerable (Of AtomFeed))" ContentType="application/atom+xml" ResponseEncoding="UTF-8" %><?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:news="http://itunes.apple.com/2011/Newsstand"><%="" %><% If Not Model Is Nothing Then%><% Dim updateDate As String = ViewData("feedUpdate")%><% If (Not String.IsNullOrEmpty(updateDate)) Then%>
<updated><%= updateDate %></updated><%
End If%><% For Each f In Model%>
<entry>
<id><%= f.id%></id>
<updated><%= f.updated%></updated>
<published><%= f.published%></published>
<news:end_date><%= f.endDate%></news:end_date>
<summary><%= f.summaryText%></summary>
<news:cover_art_icons>
<news:cover_art_icon size="SOURCE" src="<%= f.newspaperCover %>"/>
</news:cover_art_icons>
</entry><%
Next%><%
End If%>
</feed>
今天我们收到了来自itunes的邮件抱怨说他们无法导入我们的XML,而不知道它失败的原因。 渲染的XML符合他们的要求,所以我唯一的猜测就是我的视图编码存在问题。
如何在没有BOM的情况下以UTF-8正确返回此视图,以便当他们从我的给定网址中提取XML时,它将被正确处理?
编辑:
使用Darin的实现后,我最终得到了以下提要
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns:news="http://itunes.apple.com/2011/Newsstand"
xmlns="http://www.w3.org/2005/Atom">
<title type="text"></title>
<id>uuid:5fc48c36-a1d3-4280-a856-a1a0528e2552;id=1</id>
<updated>2012-07-23T00:40:00Z</updated>
<entry>
<id>23.07.2012</id>
<title type="text"></title>
<summary type="text">...</summary>
<updated>2012-07-23T00:40:00Z</updated>
<published xmlns="">2012-07-23T00:40:00Z</published>
<news:end_date>2012-07-24T00:40:00Z</news:end_date>
<news:cover_art_icons>
<news:cover_art_icon size="SOURCE"
src="https://www.someurl.com" />
</news:cover_art_icons>
</entry>
<entry>
<id>22.07.2012</id>
<title type="text"></title>
<summary type="text">...</summary>
<updated>2012-07-22T00:40:00Z</updated>
<published xmlns="">2012-07-22T00:40:00Z</published>
<news:end_date>2012-07-23T00:40:00Z</news:end_date>
<news:cover_art_icons>
<news:cover_art_icon size="SOURCE"
src="https://www.someurl.com" />
</news:cover_art_icons>
</entry>
</feed>
现在Apple的报亭无法导入以下Feed,因为他们说他们无法在此Feed的条目元素中找到元素。
答案 0 :(得分:1)
我建议您使用专为此目的设计的SyndicationFeed类,而不是在视图中手动生成XML Feed。
因此,我们假设您有一些代表您的数据的域模型:
public class NewsstandFeed
{
public DateTime? Updated { get; set; }
public IEnumerable<AtomFeed> Items { get; set; }
}
public class AtomFeed
{
public int Id { get; set; }
public DateTime Updated { get; set; }
public DateTime Published { get; set; }
public DateTime EndDate { get; set; }
public string SummaryText { get; set; }
public string NewspaperCover { get; set; }
}
然后是一个控制器,它将查询某个DAL以检索域模型:
public class HomeController : Controller
{
public ActionResult Index()
{
// Normally this will come from a database or something,
// but I am hardcoding it for demonstration purposes here
var model = new NewsstandFeed
{
Updated = DateTime.Now,
Items = new[]
{
new AtomFeed
{
Id = 1,
Updated = DateTime.Now,
Published = DateTime.Now,
EndDate = DateTime.Now,
SummaryText = "some summary",
NewspaperCover = "http://www.google.com"
}
}
};
return new NewsstandFeedResult(model);
}
}
注意控制器操作返回的NewsstandFeedResult
?我们来实现它:
public class NewsstandFeedResult : ActionResult
{
public const string NewsstandNS = "http://itunes.apple.com/2011/Newsstand";
public NewsstandFeed Model { get; private set; }
public NewsstandFeedResult(NewsstandFeed model)
{
Model = model;
if (model.Items == null)
{
model.Items = Enumerable.Empty<AtomFeed>();
}
}
public override void ExecuteResult(ControllerContext context)
{
var response = context.HttpContext.Response;
response.ContentType = "application/atom+xml";
var feed = new SyndicationFeed();
var n = new XmlQualifiedName("news", "http://www.w3.org/2000/xmlns/");
XNamespace newsstandNs = NewsstandNS;
feed.AttributeExtensions.Add(n, newsstandNs.ToString());
if (Model.Updated.HasValue)
{
feed.LastUpdatedTime = new DateTimeOffset(Model.Updated.Value.ToUniversalTime());
}
var items = new List<SyndicationItem>();
foreach (var item in Model.Items)
{
var si = new SyndicationItem();
si.Id = item.Id.ToString();
si.LastUpdatedTime = new DateTimeOffset(item.Updated.ToUniversalTime());
si.Summary = new TextSyndicationContent(item.SummaryText);
si.ElementExtensions.Add(new XElement(newsstandNs + "end_date", item.EndDate.ToUniversalTime()));
si.ElementExtensions.Add(
new XElement(
newsstandNs + "cover_art_icons",
new XElement(
newsstandNs + "cover_art_icon",
new XAttribute("size", "SOURCE"),
new XAttribute("src", item.NewspaperCover)
)
)
);
items.Add(si);
}
feed.Items = items;
using (var writer = XmlWriter.Create(response.OutputStream))
{
var formatter = new Atom10FeedFormatter(feed);
formatter.WriteTo(writer);
}
}
}
就是这样。现在只需导航到/home/index
,您将获得一个符合所有行业标准的有效Atom供稿,这样您就不必担心物料清单和物料。