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

标签 c# xml json web-services wcf

我想在 .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());
    }

}

最佳答案

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

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

WCF 是一个非常强大的通信框架,但正如上面的答案之一所述;您可以使用更简单的 HttpClient 轻松地与 REST 服务器进行通信。您提到您想要使用 JSON/XML,这意味着将来可能会扩展以支持另一种格式,因此我认为此时不使用 WCF 并遵循吻的概念。如果您使用接口(interface),您应该能够轻松更换连接代码。 (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 中最新/推荐的反序列化类?

绝对是..

JSON

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

How to: Serialize and Deserialize JSON Data

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

XML

这里有一个相当高的投票问题/答案,因为它使用 XML 来实现,其中包括示例工作代码:-

How to Deserialize XML document

How to Deserialize XML document

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

祝你好运!

关于c# - 在 .NET 4.5 或更高版本中使用 WCF 连接到远程 JSON/XML REST 服务+,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27883701/

相关文章:

php - 如何使用 php pdo 创建 JSON 嵌套对象

c - 你如何访问一个网站并阅读它在 c 中的内容?

python - 适用于 python2.7 的 Google 表格 API --> "Invalid JSON payload. Root element must be a message"

c# - 为什么 Directory.GetFiles() 在后续运行中运行得更快?

c# - CIL 数据类型及其在 C# 中的等价物

c# - TcpClient 异常死锁

c# - 使用 C# 解析 XML 文件?

c# - 与 C# 相比,F# 的性能如何?

java - 如何在 android studio 中的给定 XML 布局文件中使用 Java 动态添加按钮?

java - JAXB 解码返回空值