1

我正在尝试使用Steven提供的很好的示例作为对 StackOverFlow 问题的答案,为我的 MVC Web 应用程序实现异常处理。

在底部,提供了 Ninject 所需的配置,以便控制器可以启动并运行。我使用 Autofac 作为 IoC 容器。任何帮助定义控制器以实例化服务类将不胜感激。另外,如果我们不使用任何 IoC 容器,我有兴趣查看如何从控制器调用服务类的示例。

更新:按照史蒂文的例子,这些是我到目前为止可以写的类:

业务服务层:

namespace BusinessService.ValidationProviders
{
    public interface IValidationProvider
    {
        void Validate(object entity);
        void ValidateAll(IEnumerable entities);
    }
}   

namespace BusinessService.ValidationProviders
{
    public interface IValidator
    {
        IEnumerable<ValidationResult> Validate(object entity);
    }
}

namespace BusinessService.ValidationProviders
{
    public class ValidationResult
    {
        public ValidationResult(string key, string message)
        {
            this.Key = key;
            this.Message = message;
        }
        public string Key { get; private set; }
        public string Message { get; private set; }
    }
}

namespace BusinessService.ValidationProviders
{
    public abstract class Validator<T> : IValidator
    {
        IEnumerable<ValidationResult> IValidator.Validate(object entity)
        {
            if (entity == null) throw new ArgumentNullException("entity");

            return this.Validate((T)entity);
        }

        protected abstract IEnumerable<ValidationResult> Validate(T entity);
    }
}

namespace BusinessService.ValidationProviders
{
    public class ValidationProvider : IValidationProvider
    {
        private readonly Func<Type, IValidator> _validatorFactory;

        public ValidationProvider(Func<Type, IValidator> validatorFactory)
        {
            this._validatorFactory = validatorFactory;
        }

        public void Validate(object entity)
        {
            var results = this._validatorFactory(entity.GetType())
                .Validate(entity).ToArray();
            if (results.Length > 0) throw new ValidationException(results);
        }

        public void ValidateAll(IEnumerable entities)
        {
            var results = (
                from entity in entities.Cast<object>()
                let validator = this._validatorFactory(entity.GetType())
                from result in validator.Validate(entity)
                select result).ToArray();

            if (results.Length > 0) throw new ValidationException(results);
        }
    }
}


namespace BusinessService.ValidationProviders
{
    public sealed class NullValidator<T> : Validator<T>
    {
        protected override IEnumerable<ValidationResult> Validate(T entity)
        {
            return Enumerable.Empty<ValidationResult>();
        }
    }
}

namespace BusinessService.ValidationProviders
{
    public class ValidationException : Exception
    {
        public ValidationException(IEnumerable<ValidationResult> r)
            : base(GetFirstErrorMessage(r))
        {
            this.Errors =
                new ReadOnlyCollection<ValidationResult>(r.ToArray());
        }

        public ReadOnlyCollection<ValidationResult> Errors { get; private set; }

        private static string GetFirstErrorMessage(
            IEnumerable<ValidationResult> errors)
        {
            return errors.First().Message;
        }
    }   
}

namespace BusinessService.ValidationProviders
{
    public class NotificationValidator: Validator<NotificationViewModel>
    {
        protected override IEnumerable<ValidationResult> Validate(NotificationViewModel entity)
        {
            if (entity.PolicyNumber.Length == 0)
                yield return new ValidationResult("PolicyNumber",
                    "PolicyNumber is required.");

            if (entity.ReceivedBy.Length == 0)
                yield return new ValidationResult("ReceivedBy",
                    "ReceivedBy is required.");

            if (entity.ReceivedDate < DateTime.Now)
                yield return new ValidationResult("ReceivedDate",
                    "ReceivedDate cannot be earlier than the current date.");

        }
    }
}

namespace BusinessService
{
    public class NotificationService : INotificationService
    {
        private readonly IValidationProvider _validationProvider;

        public NotificationService(IValidationProvider validationProvider)
        {
            this._validationProvider = validationProvider;
        }

        public void CreateNotification(NotificationViewModel viewModel )
        {
            // Do validation here...
            this._validationProvider.Validate(viewModel);

            // Persist the record to the repository.
        }
    }
}

ViewModels 层:

namespace ViewModels
{
    public class NotificationViewModel
    {
        public int ID { get; set; }
        public string PolicyNumber { get; set; }
        public string ReceivedBy { get; set; }
        public DateTime ReceivedDate { get; set; }
    }
}

UI层:

namespace ExceptionHandling.Controllers
{
    public class NotificationController : Controller
    {
        private INotificationService _service;
        private IValidationProvider _validationProvider;

        public NotificationController()
        {
            _validationProvider = null; // Need to instantiate this!
            this._service = new NotificationService(_validationProvider);
        }

        public NotificationController(INotificationService service)
        {
            // Need to instantiate service here..
        }

        [HttpGet]
        public ActionResult Create()
        {
            return View();
        }

        [HttpPost]
        public ActionResult Create(NotificationViewModel viewModel)
        {
            if (ModelState.IsValid)
            {
                this._service.CreateNotification(viewModel);
                return RedirectToAction("Index", "Home");
            }
            return View();
        }
    }
}

寻找一些帮助来从控制器实例化 NotificationService 类。我们将 Autofac 用于 IoC。如果有人能指出如何为 Autofac 配置它的正确方向,那就太好了。提前谢谢了!

4

1 回答 1

0

在努力寻找将 Steven 的解决方案与 Autofac 集成的方法之后,我遇到了 Patrick Desjardin 的博客文章:

三层验证(控制器、服务和存储库)。

我发现这很容易,因为您不必注入任何验证提供程序。此外,它很容易与任何层集成。请确保您也阅读了后续帖子:

如何使用 Asp.Net MVC 正确验证模型对象

模型验证和实体框架 4.3

任何比较这两种解决方案的意见将不胜感激。非常感谢!

于 2013-08-28T14:35:55.283 回答