使用 .NET 4.5 或更高版本+中的 WCF 连接到远程 JSON/XML REST 服务

本文关键字:连接 WCF JSON 服务 REST XML 中的 NET 高版本 版本 使用 | 更新日期: 2023-09-27 18:37:15

我想在 .NET 4.5 或更高版本中使用 WCF 使用远程 REST 服务。 它适用于我正在编写的一些桌面应用程序软件。 我选择使用 WCF,因为我目前认为它是 .NET 中最合适的技术,除非有人另有说明。

该服务由 GET 或 POST(相同的响应)访问,并且可以返回指定为 URL 参数的 JSON 或 XML。 但是,即使它可以返回 XML,也没有 WSDL 文件。

我想在不使用任何第三方库的情况下访问此服务。

我的问题:

  1. WCF 是在 .NET 4.5 或更高版本中执行此操作的最佳技术吗?
  2. 哪些是合适的类/方法来连接、发送 GET 或 POST 请求并等待响应?
  3. 有没有办法告诉 WCF 使用反序列化的 json 或 xml 自动填充我的模型类,如果不是,哪个是 .NET 中最新/推荐的反序列化类?

以下是该服务的示例 URL:

XML: http://www.expasy.org/cgi-bin/prosite/PSScan.cgi?seq=ENTK_HUMAN&output=xml

JSON:http://www.expasy.org/cgi-bin/prosite/PSScan.cgi?seq=ENTK_HUMAN&output=json

下面是服务以 XML 格式返回的内容的示例:

<?xml version="1.0" encoding="UTF-8"?>
<matchset xmlns="urn:expasy:scanprosite" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:expasy:scanprosite http://expasy.org/tools/scanprosite/scanprosite.xsd" n_match="13" n_seq="1">
<match>
    <sequence_ac>P98073</sequence_ac>
    <sequence_id>ENTK_HUMAN</sequence_id>
    <sequence_db>sp</sequence_db>
    <start>54</start>
    <stop>169</stop>
    <signature_ac>PS50024</signature_ac>
    <signature_id>SEA</signature_id>
    <score>32.979</score>
    <level>0</level>
</match>
<match>
    <sequence_ac>P98073</sequence_ac>
    <sequence_id>ENTK_HUMAN</sequence_id>
    <sequence_db>sp</sequence_db>
    <start>183</start>
    <stop>222</stop>
    <signature_ac>PS50068</signature_ac>
    <signature_id>LDLRA_2</signature_id>
    <score>10.75</score>
    <level>0</level>
</match>
<match>
    <sequence_ac>P98073</sequence_ac>
    <sequence_id>ENTK_HUMAN</sequence_id>
    <sequence_db>sp</sequence_db>
    <start>197</start>
    <stop>221</stop>
    <signature_ac>PS01209</signature_ac>
    <signature_id>LDLRA_1</signature_id>
    <level_tag>(0)</level_tag>
</match>
<match>
    <sequence_ac>P98073</sequence_ac>
    <sequence_id>ENTK_HUMAN</sequence_id>
    <sequence_db>sp</sequence_db>
    <start>225</start>
    <stop>334</stop>
    <signature_ac>PS01180</signature_ac>
    <signature_id>CUB</signature_id>
    <score>13.293</score>
    <level>0</level>
</match>
<match>
    <sequence_ac>P98073</sequence_ac>
    <sequence_id>ENTK_HUMAN</sequence_id>
    <sequence_db>sp</sequence_db>
    <start>345</start>
    <stop>504</stop>
    <signature_ac>PS50060</signature_ac>
    <signature_id>MAM_2</signature_id>
    <score>42.203</score>
    <level>0</level>
</match>
<match>
    <sequence_ac>P98073</sequence_ac>
    <sequence_id>ENTK_HUMAN</sequence_id>
    <sequence_db>sp</sequence_db>
    <start>391</start>
    <stop>431</stop>
    <signature_ac>PS00740</signature_ac>
    <signature_id>MAM_1</signature_id>
    <level_tag>(0)</level_tag>
</match>
<match>
    <sequence_ac>P98073</sequence_ac>
    <sequence_id>ENTK_HUMAN</sequence_id>
    <sequence_db>sp</sequence_db>
    <start>524</start>
    <stop>634</stop>
    <signature_ac>PS01180</signature_ac>
    <signature_id>CUB</signature_id>
    <score>17.206</score>
    <level>0</level>
</match>
<match>
    <sequence_ac>P98073</sequence_ac>
    <sequence_id>ENTK_HUMAN</sequence_id>
    <sequence_db>sp</sequence_db>
    <start>642</start>
    <stop>678</stop>
    <signature_ac>PS50068</signature_ac>
    <signature_id>LDLRA_2</signature_id>
    <score>13.3</score>
    <level>0</level>
</match>
<match>
    <sequence_ac>P98073</sequence_ac>
    <sequence_id>ENTK_HUMAN</sequence_id>
    <sequence_db>sp</sequence_db>
    <start>655</start>
    <stop>677</stop>
    <signature_ac>PS01209</signature_ac>
    <signature_id>LDLRA_1</signature_id>
    <level_tag>(0)</level_tag>
</match>
<match>
    <sequence_ac>P98073</sequence_ac>
    <sequence_id>ENTK_HUMAN</sequence_id>
    <sequence_db>sp</sequence_db>
    <start>678</start>
    <stop>788</stop>
    <signature_ac>PS50287</signature_ac>
    <signature_id>SRCR_2</signature_id>
    <score>16.02</score>
    <level>0</level>
</match>
<match>
    <sequence_ac>P98073</sequence_ac>
    <sequence_id>ENTK_HUMAN</sequence_id>
    <sequence_db>sp</sequence_db>
    <start>785</start>
    <stop>1019</stop>
    <signature_ac>PS50240</signature_ac>
    <signature_id>TRYPSIN_DOM</signature_id>
    <score>39.104</score>
    <level>0</level>
</match>
<match>
    <sequence_ac>P98073</sequence_ac>
    <sequence_id>ENTK_HUMAN</sequence_id>
    <sequence_db>sp</sequence_db>
    <start>821</start>
    <stop>826</stop>
    <signature_ac>PS00134</signature_ac>
    <signature_id>TRYPSIN_HIS</signature_id>
    <level_tag>(0)</level_tag>
</match>
<match>
    <sequence_ac>P98073</sequence_ac>
    <sequence_id>ENTK_HUMAN</sequence_id>
    <sequence_db>sp</sequence_db>
    <start>965</start>
    <stop>976</stop>
    <signature_ac>PS00135</signature_ac>
    <signature_id>TRYPSIN_SER</signature_id>
    <level_tag>(0)</level_tag>
</match>
</matchset>

下面是服务在 JSON 中返回的内容的示例:

{
"n_match" : 13, "n_seq" : 1,
"matchset" : [
{"sequence_ac" : "P98073", "sequence_id" : "ENTK_HUMAN", "sequence_db" : "sp", "start" : 54, "stop" : 169, "signature_ac" : "PS50024", "signature_id" : "SEA", "score" : 32.979, "level" : 0 },{"sequence_ac" : "P98073", "sequence_id" : "ENTK_HUMAN", "sequence_db" : "sp", "start" : 183, "stop" : 222, "signature_ac" : "PS50068", "signature_id" : "LDLRA_2", "score" : 10.75, "level" : 0 },{"sequence_ac" : "P98073", "sequence_id" : "ENTK_HUMAN", "sequence_db" : "sp", "start" : 197, "stop" : 221, "signature_ac" : "PS01209", "signature_id" : "LDLRA_1", "level_tag" : "(0)"},{"sequence_ac" : "P98073", "sequence_id" : "ENTK_HUMAN", "sequence_db" : "sp", "start" : 225, "stop" : 334, "signature_ac" : "PS01180", "signature_id" : "CUB", "score" : 13.293, "level" : 0 },{"sequence_ac" : "P98073", "sequence_id" : "ENTK_HUMAN", "sequence_db" : "sp", "start" : 345, "stop" : 504, "signature_ac" : "PS50060", "signature_id" : "MAM_2", "score" : 42.203, "level" : 0 },{"sequence_ac" : "P98073", "sequence_id" : "ENTK_HUMAN", "sequence_db" : "sp", "start" : 391, "stop" : 431, "signature_ac" : "PS00740", "signature_id" : "MAM_1", "level_tag" : "(0)"},{"sequence_ac" : "P98073", "sequence_id" : "ENTK_HUMAN", "sequence_db" : "sp", "start" : 524, "stop" : 634, "signature_ac" : "PS01180", "signature_id" : "CUB", "score" : 17.206, "level" : 0 },{"sequence_ac" : "P98073", "sequence_id" : "ENTK_HUMAN", "sequence_db" : "sp", "start" : 642, "stop" : 678, "signature_ac" : "PS50068", "signature_id" : "LDLRA_2", "score" : 13.3, "level" : 0 },{"sequence_ac" : "P98073", "sequence_id" : "ENTK_HUMAN", "sequence_db" : "sp", "start" : 655, "stop" : 677, "signature_ac" : "PS01209", "signature_id" : "LDLRA_1", "level_tag" : "(0)"},{"sequence_ac" : "P98073", "sequence_id" : "ENTK_HUMAN", "sequence_db" : "sp", "start" : 678, "stop" : 788, "signature_ac" : "PS50287", "signature_id" : "SRCR_2", "score" : 16.02, "level" : 0 },{"sequence_ac" : "P98073", "sequence_id" : "ENTK_HUMAN", "sequence_db" : "sp", "start" : 785, "stop" : 1019, "signature_ac" : "PS50240", "signature_id" : "TRYPSIN_DOM", "score" : 39.104, "level" : 0 },{"sequence_ac" : "P98073", "sequence_id" : "ENTK_HUMAN", "sequence_db" : "sp", "start" : 821, "stop" : 826, "signature_ac" : "PS00134", "signature_id" : "TRYPSIN_HIS", "level_tag" : "(0)"},{"sequence_ac" : "P98073", "sequence_id" : "ENTK_HUMAN", "sequence_db" : "sp", "start" : 965, "stop" : 976, "signature_ac" : "PS00135", "signature_id" : "TRYPSIN_SER", "level_tag" : "(0)"} 
] }

以下是我已经创建的模型类,尽管我不确定是否需要创建它们,或者 WCF 是否可以为我自动执行一个模型类:

    public class PrositeScanMatchSet
    {
        public int n_match { get; set; }
        public int n_seq { get; set; }
        public PrositeScanMatch[] matchset { get; set; }
    }
    public class PrositeScanMatch
    {
        public string sequence_ac { get; set; }
        public string sequence_id { get; set; }
        public string sequence_db { get; set; }
        public int start { get; set; }
        public int stop { get; set; }
        public string signature_ac { get; set; }
        public string signature_id { get; set; }
        public float score { get; set; }
        public int level { get; set; }
        public string level_tag { get; set; }
    }

另外,这是我为创建服务查询字符串而创建的类:

public class ScanPrositeParameters
{
    /// <summary>
    /// Sequence(s) to be scanned: UniProtKB accessions e.g. P98073 or identifiers e.g. ENTK_HUMAN or PDB identifiers e.g. 4DGJ or sequences in FASTA format or UniProtKB/Swiss-Prot format. 
    /// Do not repeat parameter; multiple sequences can be specified by separating them with new lines(%0A in url).
    /// </summary>
    public string seq        ;
    /// <summary>
    /// Motif(s) to scan against: PROSITE accession e.g. PS50240 or identifier e.g. TRYPSIN_DOM or your own pattern e.g. P-x(2)-G-E-S-G(2)-[AS]. 
    /// If not specified, all PROSITE motifs are used.
    /// Do not repeat parameter; multiple motifs can be specified by separating them with new lines(%0A in url).
    /// </summary>
    public string sig        ;
    /// <summary>
    /// Target protein database for scans of motifs against whole protein databases: 'sp' (UniProtKB/Swiss-Prot) or 'tr' (UniProtKB/TrEMBL) or 'pdb' (PDB). 
    /// Only work if 'seq' is not defined.Parameter can be repeated; 1 target db by 'db' parameter.
    /// </summary>
    public string db         ;
    /// <summary>
    /// If true (defined, non empty, non zero): includes UniProtKB/Swiss-Prot splice variants. 
    /// Only works on scans against UniProtKB/Swiss-Prot.
    /// </summary>
    public string varsplic   ;
    /// <summary>
    /// Any taxonomical term e.g. 'Homo sapiens', e.g. 'Fungi; Arthropoda' or corresponding NCBI TaxID e.g. 9606, e.g. '4751; 6656' 
    /// Separate multiple terms with a semicolon.
    /// Only works on scans against UniProtKB/Swiss-Prot and UniProtKB/TrEMBL.
    /// </summary>
    public string lineage    ;
    /// <summary>
    /// Description (DE) filter: e.g. protease. 
    /// Only works on scans against UniProtKB/Swiss-Prot and UniProtKB/TrEMBL.
    /// </summary>
    public string description;
    /// <summary>
    /// Number of X characters in a scanned sequence that can be matched by a conserved position in a pattern. 
    /// Only works if 'sig' is defined, i.e.on scans of specific sequences/protein database(s) against specific motif(s). 
    /// Only works on scans against patterns.
    /// </summary>
    public string max_x      ;
    /// <summary>
    /// Output format: 'xml' or 'json' (or 'txt')
    /// </summary>
    public string output     ;
    /// <summary>
    /// If true (defined, non empty, non zero): excludes motifs with a high probability of occurrence. 
    /// Default: on.
    /// Only works if 'seq' is defined and 'sig' is not defined, i.e.on scans of specific sequence(s) against all PROSITE motifs.
    /// </summary>
    public string skip       ;
    /// <summary>
    /// If true (defined, non empty, non zero): shows matches with low level scores. 
    /// Default: off.
    /// Only works with PROSITE profiles.
    /// </summary>
    public string lowscore   ;
    /// <summary>
    /// If true (defined, non empty, non zero): does not scan against profiles. 
    /// Only works if 'seq' is defined and 'sig' is not defined, i.e.on scans of specific sequence(s) against all PROSITE motifs.
    /// </summary>
    public string noprofile  ;
    /// <summary>
    /// Mimimal number of hits per matched sequences. 
    /// Only works if 'sig' and 'db' are defined, i.e.on scans of protein database(s) against specific motif(s).
    /// </summary>
    public string minhits    ;
    public string QueryString()
    {
        var result = new Dictionary<string, string>()
        {
            {"seq", seq},
            {"sig", sig},
            {"db", db},
            {"varsplic", varsplic},
            {"lineage", lineage},
            {"description", description},
            {"max_x", max_x},
            {"output", output},
            {"skip", skip},
            {"lowscore", lowscore},
            {"noprofile", noprofile},
            {"minhits", minhits}
        };
        return String.Join("&", result.Where(a => a.Key != null && a.Value != null).Select(kvp => WebUtility.UrlEncode(kvp.Key) + "=" + WebUtility.UrlEncode(kvp.Value)).ToList());
    }
}

使用 .NET 4.5 或更高版本+中的 WCF 连接到远程 JSON/XML REST 服务

你这里有 3 个问题,所以我将回答所有问题,并以其他人的答案为基础: -

WCF 是在 .NET 4.5 或更高版本中执行此操作的最佳技术吗?

WCF 是一个非常强大的通信框架,但正如上述答案之一所述;您可以使用更简单的 HttpClient 非常轻松地与 REST 服务器进行通信。您提到您希望使用 JSON/XML,这意味着将来可能会对其进行扩展以支持另一种格式,因此我认为此时不使用 WCF 并遵循 KISS 的概念会更合适。如果使用接口,您应该能够轻松换出连接代码。(http://en.wikipedia.org/wiki/KISS_principle)

我相信你已经对WCF做了很多研究,但如果没有,看看 http://msdn.microsoft.com/en-us/library/ms731082%28v=vs.110%29.aspx。MSDN 文档非常适合入门。

哪些是合适的类/方法来连接、发送 GET 或 POST 请求并等待响应?

这已经得到了回答;你的客户端已经知道它是否在请求xml/json,所以你只需将数据传递给适当的读取器,该阅读器将解析JSON/XML/其他格式。

幸运的是,.NET 有许多 API 可用于帮助您解析这些语言,这将有助于回答您的最后一个问题。

有没有办法告诉 WCF 使用反序列化的 json 或 xml 自动填充我的模型类,如果不是,哪个是 .NET 中最新/推荐的反序列化类?

最肯定的是..

杰伦

见 http://msdn.microsoft.com/en-us/library/bb412179%28v=vs.110%29.aspx

如何:序列化和反序列化 JSON 数据

这将向您展示如何将 JSON 数据反序列化到模型类中;这也详细说明了如何使用 WCF 执行此操作,因此这可能对您非常有用。这包括用于使用 DataContractJsonSerializer 反序列化 JSON 的推荐类。建议使用它,因为这些类不依赖于 C# 编译器,而 .NET 3.5/4 之前最常用的方法之一则依赖于 C# 编译器。

.XML

对于使用包含示例工作代码的XML进行操作,这里有相当高投票的问题/答案:-

如何反序列化 XML 文档

如何反序列化 XML 文档

确保您查看使用 XSD 的未接受答案以及已接受的答案。两种可行的解决方案;使用您认为适合您的内容!:)

祝你好运!

当服务器支持 REST Get 接口时,使用 WCF 似乎有点矫枉过正。

XDocument 类可以读取 XML URI。

var doc = XDocument.Load("http://www.expasy.org/cgi-bin/prosite/PSScan.cgi?seq=ENTK_HUMAN&output=xml");

然后,可以使用 LINQ 查找数据。 有关更多详细信息,请参阅基本查询 http://msdn.microsoft.com/en-us/library/bb943906.aspx。

我建议查看HttpClient以从远程服务中检索JSon。

http://www.asp.net/web-api/overview/advanced/calling-a-web-api-from-a-net-client