잊지 않겠습니다.

Javascript가 동작하지 않는 브라우져나 서버단에 치명적인 오류가 들어갈 수 있는 값의 경우에는 Server단에서의 Validation Check가 반드시 필요하게 된다. 전에 사용했던 IDataError interface의 경우에는 데이터 모델들의 처리가 되는데. 이는 일반적인 C#에서의 에러처리가 아닌 ASP .NET MVC에서의 Validateion 처리라고 조금은 한정지어서 생각할 수 있다.

생각해보면 C# 언어에 가장 맞는 Validation Check는 try~catch 를 이용한 방법이다. 이러한 방법을 이용해야지만이 만약 Entity를 다른 환경, 예를 들어 SilverLight에서 Entity를 표현하거나 WinForm으로 Entity를 표현할 때에 정확한 Validation Check가 가능하게 된다.

다음은 Product에 대한 Validation check code이다.

public class Product
{        
    public string Name { get; set; }
    public string Price { get; set; }
    public string Description { get; set; }

    public void CheckValidation()
    {
        ProductException exception = new ProductException();
        if(string.IsNullOrWhiteSpace(Name))
        {
            exception.Add("name", "Name is empty");
        }

        if(string.IsNullOrWhiteSpace(Description))
        {
            exception.Add("description", "Description is empty");
        }

        if(string.IsNullOrEmpty(Price))
        {
            exception.Add("Price", "Price is empty");
        }

        if(!exception.IsValid)
        {
            throw exception;
        }
    }
}

public class ProductException : Exception, IDictionary
{
    public bool IsValid { get { return _exceptMessages.Count == 0; } }
    private Dictionary _exceptMessages;
    public ProductException()            
    {
        _exceptMessages = new Dictionary();
    }

    #region IDictionary Members

    public void Add(string key, string value)
    {
        _exceptMessages.Add(key, value);
    }

    public bool ContainsKey(string key)
    {
        return _exceptMessages.ContainsKey(key);
    }

    public ICollection Keys
    {
        get { return _exceptMessages.Keys; }
    }

    public bool Remove(string key)
    {
        return _exceptMessages.Remove(key);
    }

    public bool TryGetValue(string key, out string value)
    {
        return _exceptMessages.TryGetValue(key, out value);
    }

    public ICollection Values
    {
        get { return _exceptMessages.Values; }
    }

    public string this[string key]
    {
        get
        {
            return _exceptMessages[key];
        }
        set
        {
            _exceptMessages[key] = value;
        }
    }

    #endregion

    #region ICollection> Members

    public void Add(KeyValuePair item)
    {
        _exceptMessages.Add(item.Key, item.Value);
    }

    public void Clear()
    {
        _exceptMessages.Clear();
    }

    public bool Contains(KeyValuePair item)
    {
        return _exceptMessages.Contains(item);
    }

    public void CopyTo(KeyValuePair[] array, int arrayIndex)
    {
        throw new NotImplementedException();
    }

    public int Count
    {
        get { return _exceptMessages.Count; }
    }

    public bool IsReadOnly
    {
        get { throw new NotImplementedException(); }
    }

    public bool Remove(KeyValuePair item)
    {
        return _exceptMessages.Remove(item.Key);
    }

    #endregion

    #region IEnumerable> Members

    public IEnumerator> GetEnumerator()
    {
        return _exceptMessages.GetEnumerator();
    }

    #endregion

    #region IEnumerable Members

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return _exceptMessages.GetEnumerator();
    }

    #endregion
}
Product을 사용하는 Controller의 예
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult New(Product productValue)
{
    try
    {
        productValue.CheckValidation();
    }
    catch(ProductException ex)
    {
        foreach(string key in ex.Keys)
        {
            ModelState.AddModelError(key, ex[key]);
        }                
        return View();
    }

    return RedirectToAction("NewResult",
        new { product = productValue });
}

Posted by Y2K
,