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

C# 使用.NET 4.5或更高版本中的WCF连接到远程JSON/XML REST服务+;,c#,xml,json,web-services,wcf,C#,Xml,Json,Web Services,Wcf,我想使用.NET4.5或更高版本中的WCF使用远程REST服务。这是我正在写的一些桌面应用软件。我选择使用WCF,因为我目前认为它是.NET中最合适的技术,除非有人另有说明 该服务由GET或POST(相同的响应)访问,可以返回指定为URL参数的JSON或XML。然而,即使它可以返回XML,也没有WSDL文件 我希望在不使用任何第三方库的情况下访问此服务 我的问题是: WCF是在.NET4.5或更高版本中实现这一点的最佳技术吗 连接、发送GET或POST请求并等待响应的合适类/方法有哪些 有没有办

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

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

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

我的问题是:

  • WCF是在.NET4.5或更高版本中实现这一点的最佳技术吗
  • 连接、发送GET或POST请求并等待响应的合适类/方法有哪些
  • 有没有办法告诉WCF自动用反序列化的json或xml填充我的模型类?如果没有,在.NET中哪个是最新/推荐的反序列化类
  • 以下是该服务的URL示例:

    XML:

    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>
    
    以下是我已经制作的模型类,尽管我不确定是否需要制作它们,或者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());
        }
    
    }
    
    公共类ScanPrositeParameters
    {
    /// 
    ///待扫描序列:UniProtKB访问,如P98073或标识符,如ENTK_人类或PDB标识符,如4DGJ或FASTA格式或UniProtKB/Swiss-Prot格式的序列。
    ///不要重复参数;可以通过使用新行分隔多个序列(url中的(%0A))来指定多个序列。
    /// 
    公共字符串序列;
    /// 
    ///要扫描的模体:原生质体加入,例如PS50240或标识符,例如胰蛋白酶或您自己的模式,例如P-x(2)-g-e-s-g(2)-(AS)。
    ///如果未指定,则使用所有PROSITE图案。
    ///不要重复参数;可以通过使用新行分隔多个基序(url中的(%0A))来指定多个基序。
    /// 
    公共字符串sig;
    /// 
    ///针对整个蛋白质数据库扫描基序的目标蛋白质数据库:“sp”(UniProtKB/Swiss-Prot)或“tr”(UniProtKB/TrEMBL)或“pdb”(pdb)。
    ///仅在未定义“seq”时工作。参数可以重复;1个目标db乘以“db”参数。
    /// 
    公共字符串数据库;
    /// 
    ///如果为true(已定义,非空,非零):包括UniProtKB/Swiss Prot剪接变体。
    ///仅适用于针对UniProtKB/Swiss Prot的扫描。
    /// 
    公共字符串varsplic;
    /// 
    ///任何分类术语,如“智人”,如“真菌;节肢动物”或相应的NCBI分类术语,如9606,如“4751;6656”
    ///用分号分隔多个术语。
    ///仅适用于针对UniProtKB/Swiss Prot和UniProtKB/TrEMBL的扫描。
    /// 
    公共弦谱系;
    /// 
    ///说明(DE)过滤器:例如蛋白酶。
    ///仅适用于针对UniProtKB/Swiss Prot和UniProtKB/TrEMBL的扫描。
    /// 
    公共字符串描述;
    /// 
    ///扫描序列中可由模式中的保守位置匹配的X字符数。
    ///仅当定义了“sig”时有效,即针对特定基序扫描特定序列/蛋白质数据库。
    ///仅适用于针对模式的扫描。
    /// 
    公共字符串max_x;
    /// 
    ///输出格式:“xml”或“json”(或“txt”)
    /// 
    公共字符串输出;
    /// 
    ///如果为真(已定义,非空,非零):排除出现概率高的图案。
    ///默认值:打开。
    ///仅当定义了“seq”而未定义“sig”时有效,即针对所有PROSITE基序对特定序列进行扫描。
    /// 
    公共字符串跳过;
    /// 
    ///如果为真(已定义,非空,非零):显示低级别分数的匹配项。
    ///默认值:关闭。
    ///仅适用于PROSITE配置文件。
    /// 
    公共字符串低分;
    /// 
    ///如果为true(已定义,非空,非零):不扫描配置文件。
    ///仅当定义了“seq”而未定义“sig”时有效,即针对所有PROSITE基序对特定序列进行扫描。
    /// 
    公共字符串非营利组织;
    /// 
    ///每个匹配序列的最小命中数。
    ///仅当定义了“sig”和“db”时有效,即针对特定基序扫描蛋白质数据库。
    /// 
    公共字符串minhits;
    公共字符串查询字符串()
    {
    var result=newdictionary()
    {
    {“seq”,seq},
    {“sig”,sig},
    {“db”,db},
    {“varsplic”,varsplic},
    {“血统”,血统},
    {“描述”,描述},
    {“max_x”,max_x},
    {“输出”,输出},
    {“跳过”,跳过},
    {“lowscore”,lowscore},
    {“noprofile”,noprofile},
    {“minhits”,minhits}
    };
    返回String.Join(“&”,result.Where(a=>a.Key!=null&&a.Value!=null)。选择(kvp=>WebUtility.UrlEncode(kvp.Key)+“=”+WebUtility.UrlEncode(kvp.Value)).ToList();
    }
    }
    
    当服务器支持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定位数据。有关更多详细信息,请参阅基本查询。

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


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

    在.NET 4.5或更高版本中,WCF是实现这一点的最佳技术吗?

    WCF是一个非常强大的通信框架,但作为上述答案之一;您可以非常轻松地使用更简单的HttpClient与REST服务器通信。您提到您想要使用JSON/XML,这意味着,在将来,可能
    var doc = XDocument.Load("http://www.expasy.org/cgi-bin/prosite/PSScan.cgi?seq=ENTK_HUMAN&output=xml");