zoukankan      html  css  js  c++  java
  • 博客园客户端(Universal App)开发随笔 -- 数据基础准备

    在开始之前,我们先了解下博客园提供的接口:

    博客: http://wcf.open.cnblogs.com/blog/help
    新闻: http://wcf.open.cnblogs.com/news/help

    博客园_48小时阅读排行为例,返回的Xml如下图(RSS,如果你用IE打开的话,会提示你订阅。。)。

    博客园_48小时阅读排行

    博客园的大部分API返回的都是RSS(还提供分页!),如果只是做一个简单的RSS reader,可以直接用SyndicationClient,在RetrieveFeedAsync后会把XML解析成SyndicationFeed

    但是为了绑定方便和兼顾其他非RSS的API,我们的决定自定义实体类,然后用XmlSerializer反序列化,使用反序列化可以省去使用XmlDocument或者linq to xml解析的代码。

    建立工程:

    因为我们准备做Universal App,这里我们建立一个支持可移植库(Portable for Universal Apps)。

    这个库其实就是之前所谓的PCL,只不过默认支持的只有Windows 8.1和Windows phone8.1。

    实体类

    对于返回RSS的API,我们首先需要定义Feed<T>类,用来包含feed的基本信息,Entries属性对应XML中所有的entry节点,之所以是泛型,是因为很多entry的属性是不一样的。

    // Feed<T>对应的是feed节点,命名空间是必须的,否则找不到节点
          [XmlRoot("feed", Namespace = "http://www.w3.org/2005/Atom")]
          public class Feed<T>
          {
              // Id属性对应的是feed/id节点的值
              [XmlElement("id")]
              public string Id { get; set; }
      
              [XmlElement("title")]
             public string Title { get; set; }
     
             // XmlSerializer会把feed下所有entry节点解析成对应的实体,然后放入List
             [XmlElement("entry")]
             public List<T> Entries { get; set; }
         }

    有了Feed<T> 之后,针对不同的API定义实体类, 如推荐博主的Blogger。

    // 这个root 就不需要namespace了,因为Feed已经有了,反序列化的时候使用Feed<Blogger>即可
        [XmlRoot("entry")]
        public class Blogger
        {
            [XmlElement("id")]
            public string Id { get; set; }
    
            [XmlElement("title")]
            public string Name { get; set; }
    
            [XmlElement("updated")]
            public string UpdateTimeString { get; set; }
    
            [XmlElement("link", typeof(Link))]
            public Link Link { get; set; }
    
            [XmlElement("blogapp")]
            public string BlogApp { get; set; }
    
            [XmlElement("avatar")]
            public string Avatar { get; set; }
    
            [XmlElement("postcount")]
            public string PostCount { get; set; }
    
            [XmlIgnore]
            public DateTime UpdateTime
            {
                get { return Functions.ParseDateTime(this.UpdateTimeString); }
            }
        }

    对于新闻和博客,大部分属性都是一样的,所以我们定义了一个EntryBase基类(起名字什么的最头疼了。。),其他的可以参考我们的github上源代码,地址在文章末尾处。

    [XmlRoot(ElementName = "entry")]
        public class EntryBase
        {
            [XmlElement("id")]
            public string ID { get; set; }
    
            [XmlElement("title")]
            public string Title { get; set; }
    
            [XmlElement("summary")]
            public string Summary { get; set; }
    
            [XmlElement("published")]
            public string PublishTimeString { get; set; }
    
            [XmlElement("link", typeof(Link))]
            public Link Link { get; set; }
    
            [XmlElement("blogapp")]
            public string BlogApp { get; set; }
    
            [XmlElement("diggs")]
            public string DiggsCount { get; set; }
    
            [XmlElement("views")]
            public string ViewsCount { get; set; }
    
            [XmlElement("comments")]
            public string CommentsCount { get; set; }
    
            [XmlIgnore]
            public PostStatus Status{ get; set; }
    
            [XmlIgnore]
            public DateTime PublishTime
            {
                get
                {
                    return Functions.ParseDateTime(this.PublishTimeString);
                }
            }
        }

    其中UpdateTime需要注意的是,博客园的部分API返回的DateTime字符串在反序列化时会出错(应该是后面少了时区什么的),所以这里直接用的是string(这里偷懒了。。),然后应用内使用的时候自己解析。

    非RSS的新闻内容:

    XmlElementAttribute没有写节点名称的话,说明节点名称和属性名是一样(包括大小写),如下面这段Xml。

    <?xml version="1.0" encoding="utf-8"?><NewsBody xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><Title>90后创业者孙宇晨:我衡量人的标准就是你赚多少钱</Title><SourceName>投资界</SourceName><SubmitDate>2014-12-15 16:30:59</SubmitDate><Content>我现在衡量别人的标准,这个人为社会...</Content><ImageUrl>https://images0.cnblogs.com/news/66372/201412/151630299226167.jpg</ImageUrl><PrevNews>510939</PrevNews><NextNews/><CommentCount>0</CommentCount></NewsBody>
    public class NewsBody
        {
            [XmlElement]
            public string SubmitDateString { get; set; }
    
            [XmlElement]
            public string Content { get; set; }
    
            [XmlElement]
            public string ImageUrl { get; set; }
    
            [XmlElement]
            public string PrevNews { get; set; }
    
            [XmlElement]
            public string NextNews { get; set; }
    
            [XmlElement]
            public string CommentCount { get; set; }
    
            [XmlElement]
            public string Title { get; set; }
    
            [XmlIgnore]
            public DateTime SubmitDate
            {
                get {
                    return Functions.ParseDateTime(this.SubmitDateString);
                }
            }
        }
    public class NewsBody
        {
            [XmlElement]
            public string SubmitDateString { get; set; }
    
            [XmlElement]
            public string Content { get; set; }
    
            [XmlElement]
            public string ImageUrl { get; set; }
    
            [XmlElement]
            public string PrevNews { get; set; }
    
            [XmlElement]
            public string NextNews { get; set; }
    
            [XmlElement]
            public string CommentCount { get; set; }
    
            [XmlElement]
            public string Title { get; set; }
    
            [XmlIgnore]
            public DateTime SubmitDate
            {
                get {
                    return Functions.ParseDateTime(this.SubmitDateString);
                }
            }
        }

    Http数据请求

    目前winrt中可以用来实现Http数据请求的类至少有3个:WebRequest,Windows.Web.Http.HttpClient和System.Net.Http.HttpClient和System.Net.Http.HttpClient。

    建议使用Windows.Web.Http.HttpClient这个新加的类,另一个HttpClient可能在以后的某个版本中被砍掉,MSDN对于这点有专门的提醒,至于WebRequest使用则起来没有新的HttpClient方便。

    HttpClient提供常用的Http请求方法:GetAsync, DeleteAsync, PostAsync和GetStringAsync,其中GetStringAsync用来请求XML/Json时相当方便,省去了从response.content转成string的过程(但是也得不到HttpStatusCode了,有得有失。。),使用如下:

    HttpClient client = new HttpClient();
    
    try
    {
      string xmlString = await client.GetStringAsync(new Uri(“API URL here”));
    }
    catch(Exception)
    {
      //网络不可用时会抛出异常
    }

    数据请求就是这么简单,剩下的就是根据不同需求来拼接API的URL。

    PS:当网络不可用的时候,请求会抛出System.Exception,带着错误代码,切记要捕获这个异常。

     

    小结

    使用HttpClient获得Xml数据是非常简单的,而有了XmlSerializer更可以把从Xml到实体类的映射过程简化。欢迎大家继续关注。

    Windows Phone Store App link:

    http://www.windowsphone.com/zh-cn/store/app/博客园-uap/500f08f0-5be8-4723-aff9-a397beee52fc

    Windows Store App link:

    http://apps.microsoft.com/windows/zh-cn/app/c76b99a0-9abd-4a4e-86f0-b29bfcc51059

    GitHub open source link:

    https://github.com/MS-UAP/cnblogs-UAP

    MSDN Sample Code:

    https://code.msdn.microsoft.com/CNBlogs-Client-Universal-477943ab

  • 相关阅读:
    C# 创建一个日志文件
    C# WinForm程序添加引用后调用静态方法时报“Interfaces_Helper.Global”的类型初始值设定项引发异常。---> System.NullReferenceException: 未将对象引用设置到对象的实例。
    SqlServer 一些操作
    多线程处理sql server2008出现Transaction (Process ID) was deadlocked on lock resources with another process and has been chose问题
    SQL
    WinForm 弹框确认后执行
    C#强制清除缓存
    C#TextBox自动滚动到最低端
    XmlDocument To String
    ROCK 算法
  • 原文地址:https://www.cnblogs.com/ms-uap/p/4166806.html
Copyright © 2011-2022 走看看