0

我正在维护一个旧版 WebForms 应用程序,其中一个页面只提供 GET 请求并使用许多查询字符串参数。这项工作在代码隐藏中完成,并进行了大量此类检查和强制转换。

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
}

我想创建一个可测试的类来封装这个解析和验证并将其移出代码隐藏。任何人都可以推荐一些方法和/或示例吗?

4

2 回答 2

2

作为第一步,我可能会创建某种形式的映射器/翻译器对象,如下所示:

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...
}

然后你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
    }
}

我省略了我创建的特定异常的代码,并假设您在后面页面的某处实例化了一个映射器。

测试这个新对象应该是微不足道的;您在传入的集合上设置参数Map,然后断言请求对象上的正确参数具有您期望的值。您甚至可以通过检查它是否在正确的情况下引发异常来测试日志消息。

于 2012-12-28T06:54:31.113 回答
1

假设您可能有许多这样的页面使用此类参数解析,首先创建一个简单的静态类,在NamedValueCollection上具有扩展方法。例如,

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);
    }

    // ...    
}

如下使用它

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

下一步将是编写特定于页面的解析器类。例如,

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;

        // ...  
    }
}
于 2012-12-28T07:06:49.573 回答