WCF DataServices服务操作参数 - 字符替换

时间:2012-07-09 08:56:49

标签: wcf-data-services silverlight-5.0 service-operations

我有一个非常奇怪的问题(使用SL5,WCF DataServices 5.0.1): 我有一个ServiceOperation,带有2个字符串参数(用户名,密码),用于检查用户是否存在

public IQueryable<User> Login(string username, string password)
{...}

当我尝试调用此方法时,Everythings工作正常,但密码哈希中包含“+”字符的情况除外。在这种情况下,似乎它被替换为空白字符:

var pwd = CRQWKrKzCcQVnlhk2zl0j5QM+c5ujQGMv0XXnh4genI=
this.Context.BeginExecute<User>(new Uri(string.Format("/Login?username='{0}'&password='{1}'", username, pwd), UriKind.Relative), (ar) => { .. }, null);

如果我用Fiddler抓住它,Request-Header对我来说似乎没问题......

GET /Service.svc/Login?username='xyz'&password='CRQWKrKzCcQVnlhk2zl0j5QM+c5ujQGMv0XXnh4genI=' HTTP/1.1

但是在WebForms-Tab中,Password-QueryString已经有一个空格而不是'+'。如果我在服务器上调试它,结果相同......

你们中有谁知道“+”被替换的原因吗? 还有其他无效字符吗? 我怎么能避免这种情况?

更新/编辑:

令人惊讶的是,以下查询按预期工作:

var query = (DataServiceQuery<User>) from c in this.Context.Users
                                             where
                                                 c.Username.Equals(username.ToLower()) &&
                                                 c.Password.Equals(Cryptography.ComputeSha256Hash(password + username.ToLower())) 
                                             select c;

提前致谢!

2 个答案:

答案 0 :(得分:1)

需要正确编码URL的查询字符串部分。对WCF DS客户端LINQ提供程序(例如,context.Users.Where(...))的调用由客户端堆栈自动编码。对context.Execute的调用不会以这种方式修改URL,因此其中的值将需要由其他代码进行编码。

在Visual Studio中尝试以查看差异:

using System;
using System.Data.Services.Client;
using System.Linq;

namespace Scratch
{
    public class Program
    {
        public static void Main()
        {
            var context = new DataServiceContext(new Uri("http://services.odata.org/OData/OData.svc/"));
            var query1 = context.CreateQuery<Category>("Categories").Where(c => c.Name == "abcd+efgh=ijlk");
            var query2 = context.Execute<Category>(new Uri("http://services.odata.org/OData/OData.svc/Categories()?$filter=Name eq 'abcd+efgh=ijlk'"));
            Console.WriteLine("context.Categories.Where(...): {0}", query1.ToString());
            Console.WriteLine("context.Execute<Category>(...): {0}", ((QueryOperationResponse)query2).Query.ToString());
        }
    }

    public class Category
    {
        public int ID { get; set; }
        public string Name { get; set; }
    }
}

答案 1 :(得分:1)

感谢Mark Stafford的提示。 我现在已经解决了这个问题:

var pwd = Uri.EscapeDataString(Cryptography.ComputeSha256Hash(password + username.ToLower()));

查询现在看起来像这样:

/GET Service.svc/Login?username='xyz'&password='CRQWKrKzCcQVnlhk2zl0j5QM%252Bc5ujQGMv0XXnh4genI%253D'

在服务器上等效的取消行为:

var pwd = Uri.UnescapeDataString(password);

请参阅http://www.codebadger.com/blog/post/2010/08/10/Use-EscapeUriString-instead-of-UrlEncode-for-Silverlight.aspx