简体   繁体   English

验证和解析ASP.NET中的url参数

[英]Validating and parsing url parameters in ASP.NET

I'm maintaining a legacy WebForms application and one of the pages just serves GET requests and works with many query string parameters. 我维护的是旧版WebForms应用程序,其中一个页面仅处理GET请求并与许多查询字符串参数一起使用。 This work is done in the code-behind and does a lot of this type of check and casting. 这项工作是在后台代码中完成的,并且会执行很多此类检查和转换。

protected override void OnLoad(EventArgs e)
{
    string error = string.Empty;

    string stringParam = Request.Params["stringParam"];
    if (!String.IsNullOrEmpty(stringParam))
    {
        error = "No parameter";
        goto LoadError;
    }

    Guid? someId = null;
    try
    {
        someId = new Guid(Request.Params["guidParam"]);
    }
    catch (Exception){}
    if (!someId.HasValue)
    {
        error = "No valid id";
        goto LoadError;
    }

    // parameter checks continue on

LoadError:
    log.ErrorFormat("Error loading page: {0}", error);
    // display error page
}

I'd like to create a testable class that encapsulates this parsing and validation and moves it out of the code-behind. 我想创建一个可测试的类来封装此解析和验证,并将其移出代码隐藏区。 Can anyone recommend some approaches to this and/or examples? 谁能为这个和/或示例推荐一些方法?

As a first big step, I'd probably create some form of mapper/translator object, like this: 作为第一步,我可能会创建某种形式的mapper / translator对象,如下所示:

class SpecificPageRequestMapper 
{
    public SpecificPageRequest Map(NameValueCollection parameters)
    {
        var request = new SpecificPageRequest();
        string stringParam = parameters["stringParam"];
        if (String.IsNullOrEmpty(stringParam))
        {
            throw new SpecificPageRequestMappingException("No parameter");
        }

        request.StringParam = stringParam;

        // more parameters

        ...

        return request;
    }
}

class SpecificPageRequest
{
    public string StringParam { get; set; }
    // more parameters...
}

Then your OnLoad could look like this: 然后您的OnLoad可能如下所示:

protected override void OnLoad(EventArgs e)
{  
    try
    {
        var requestObject = requestMapper.Map(Request.Params);
        stringParam = requestObject.StringParam;
        // so on, so forth. Unpack them to the class variables first.
        // Eventually, just use the request object everywhere, maybe.
    }
    catch(SpecificPageRequestMappingException ex)
    {
        log.ErrorFormat("Error loading page: {0}", ex.Message);
        // display error page
    }
}

I've omitted the code for the specific exception I created, and assumed you instantiate a mapper somewhere in the page behind. 我已经为我创建的特定异常省略了代码,并假定您在后面页面的某个地方实例化了一个映射器。

Testing this new object should be trivial; 测试这个新对象应该很简单。 you set the parameter on the collection passed into Map , then assert that the correct parameter on the request object has the value you expect. 您可以在传递给Map的集合上设置参数,然后断言请求对象上的正确参数具有您期望的值。 You can even test the log messages by checking that it throws exceptions in the right cases. 您甚至可以通过检查在适当情况下是否引发异常来测试日志消息。

Assuming that you may have many such pages using such parameter parsing, first create a simple static class having extension methods on NamedValueCollection . 假设使用此类参数解析可能有许多此类页面,请首先在NamedValueCollection上创建一个具有扩展方法的简单静态类。 For example, 例如,

static class Parser
{    
    public static int? ParseInt(this NamedValueCollection params, string name)
    {
        var textVal = params[name];
        int result = 0;
        if (string.IsNullOrEmpty(textVal) || !int.TryParse(textVal, out result))
        {
            return null;
        }
        return result;
    }

   public static bool TryParseInt(this NamedValueCollection params, string name, out int result)
    {
        result = 0;
        var textVal = params[name];
        if (string.IsNullOrEmpty(textVal))
            return false;
        return int.TryParse(textVal, out result);
    }

    // ...    
}

Use it as follows 如下使用

int someId = -1;
if (!Request.Params.TryParseInt("SomeId", out someId))
{
   // error
}

Next step would be writing page specific parser class. 下一步将是编写页面特定的解析器类。 For example, 例如,

public class MyPageParser
{
    public int? SomeId { get; private set; } 
    /// ...

    public IEnumerable<string> Parse(NamedValueCollection params)
    {
        var errors = new List<string>();
        int someId = -1;
        if (!params.TryParseInt("SomeId", out someId))
        {
            errors.Add("Some id not present");
            this.SomeId = null;
        }
        this.SomeId = someId;

        // ...  
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM