【问题标题】:Validating and parsing url parameters in ASP.NET在 ASP.NET 中验证和解析 url 参数
【发布时间】:2012-12-28 06:28:33
【问题描述】:

我正在维护一个旧版 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
}

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

【问题讨论】:

  • goto?不要每天都看到。
  • 是的,没错,这也是重构目标之一。

标签: c# asp.net oop validation refactoring


【解决方案1】:

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

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 的集合上设置参数,然后断言请求对象上的正确参数具有您期望的值。您甚至可以通过检查它是否在正确的情况下引发异常来测试日志消息。

【讨论】:

    【解决方案2】:

    假设你可能有很多这样的页面使用这样的参数解析,首先创建一个简单的静态类,在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;
    
            // ...  
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-12-20
      • 1970-01-01
      • 2010-09-22
      • 1970-01-01
      • 2016-09-25
      • 2011-04-15
      • 1970-01-01
      相关资源
      最近更新 更多