Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/280.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在N层、域驱动设计、MVC应用程序中处理异常_C#_Exception Handling_Domain Driven Design - Fatal编程技术网

C# 在N层、域驱动设计、MVC应用程序中处理异常

C# 在N层、域驱动设计、MVC应用程序中处理异常,c#,exception-handling,domain-driven-design,C#,Exception Handling,Domain Driven Design,我构建了一个MVC应用程序,如下所示: MVC应用程序-应用程序层-业务层-存储库-数据 我阅读了应用程序的代码,发现似乎没有人以类似于数据传递的方式传递异常 换句话说,数据通过接口引用,并在不同的上下文中重用。如果数据层发生异常,如何将其发送到GUI或相关层?应该使用接口吗?应用程序中处理异常的结构是什么?我没有阅读链接的文档,但我有一个简单的例子,在这个例子中,我提出异常以响应无法满足不变量的情况。假设我正在创建一个实例,但由于某种原因它是“无效的”,比如说用户输入错误。与其让我的实体处于无

我构建了一个MVC应用程序,如下所示:

MVC应用程序-应用程序层-业务层-存储库-数据

我阅读了应用程序的代码,发现似乎没有人以类似于数据传递的方式传递异常


换句话说,数据通过接口引用,并在不同的上下文中重用。如果数据层发生异常,如何将其发送到GUI或相关层?应该使用接口吗?应用程序中处理异常的结构是什么?

我没有阅读链接的文档,但我有一个简单的例子,在这个例子中,我提出异常以响应无法满足不变量的情况。假设我正在创建一个实例,但由于某种原因它是“无效的”,比如说用户输入错误。与其让我的实体处于无效状态(在DDD中是no-no)并让系统“验证”它,不如在创建它时抛出一个异常。相关的“验证消息”(针对用户)是从未满足的同一规范实例中提取的,并且我的派生异常包含UI需要的值

不变量异常的示例:

public class InvariantException : MyAppException
{
    public object FailingObject = null;
    public ModelStateDictionary ModelState = new ModelStateDictionary();


    public InvariantException() { }

    public InvariantException(object failingObject, ModelStateDictionary messages)
    {
        this.FailingObject = failingObject;
        this.ModelState = messages;
    }

    public InvariantException(object failingObject, ModelStateDictionary messages,
        Exception innerException)
        : base("refer to ModelState", innerException)
    {
        this.FailingObject = failingObject;
        this.ModelState = messages;
    }
}
public class PostFieldLengthSpecification : ISpecification<Post>
{
    private  const string TITLE_LENGTH_RANGE = "5-100";
    private  const string BODY_LENGTH_RANGE = "20-10000";


    public bool IsSatisfiedBy(Post post)
    {
        return this.GetErrors(post).IsValid;
    }


    public ModelStateDictionary GetErrors(Post post)
    {
        ModelStateDictionary modelState = new ModelStateDictionary();

        if (!post.Title.Trim().Length.Within(TITLE_LENGTH_RANGE))
            modelState.AddModelError(StongTypeHelpers.GetPropertyName((Post p) => p.Title),
                "Please make sure the title is between {0} characters in length".With(TITLE_LENGTH_RANGE));

        if (!post.BodyMarkup.Trim().Length.Within(BODY_LENGTH_RANGE))
            modelState.AddModelError(StongTypeHelpers.GetPropertyName((Post p) => p.BodyMarkup),
                "Please make sure the post is between {0} characters in length".With(BODY_LENGTH_RANGE));

        return modelState;
    }
}
    public static Post GetNewPost(string title, string bodyMarkup, DateTime posted)
    {
        var post = new Post(0, title, bodyMarkup, posted, new List<Comment>());
        var fieldLengthSpec = new PostFieldLengthSpecification();

        if (fieldLengthSpec.IsSatisfiedBy(post))
            return post;
        else
            throw new InvariantException(post, fieldLengthSpec.GetErrors(post));
    }
public class PostModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        if (bindingContext.ModelType == typeof(Post))
        {
            try
            {
                // Create Post
                return base.BindModel(controllerContext, bindingContext);
            }
            catch (InvariantException ie)
            {
                // If invalid, add errors from factory to ModelState
                bindingContext.ModelState.AddNewErrors(ie.ModelState);
                bindingContext.ModelState.AddValuesFor<Post>(bindingContext.ValueProvider);
                return ie.FailingObject;
            }
        }
为用户/UI返回相关“验证消息”的规范示例:

public class InvariantException : MyAppException
{
    public object FailingObject = null;
    public ModelStateDictionary ModelState = new ModelStateDictionary();


    public InvariantException() { }

    public InvariantException(object failingObject, ModelStateDictionary messages)
    {
        this.FailingObject = failingObject;
        this.ModelState = messages;
    }

    public InvariantException(object failingObject, ModelStateDictionary messages,
        Exception innerException)
        : base("refer to ModelState", innerException)
    {
        this.FailingObject = failingObject;
        this.ModelState = messages;
    }
}
public class PostFieldLengthSpecification : ISpecification<Post>
{
    private  const string TITLE_LENGTH_RANGE = "5-100";
    private  const string BODY_LENGTH_RANGE = "20-10000";


    public bool IsSatisfiedBy(Post post)
    {
        return this.GetErrors(post).IsValid;
    }


    public ModelStateDictionary GetErrors(Post post)
    {
        ModelStateDictionary modelState = new ModelStateDictionary();

        if (!post.Title.Trim().Length.Within(TITLE_LENGTH_RANGE))
            modelState.AddModelError(StongTypeHelpers.GetPropertyName((Post p) => p.Title),
                "Please make sure the title is between {0} characters in length".With(TITLE_LENGTH_RANGE));

        if (!post.BodyMarkup.Trim().Length.Within(BODY_LENGTH_RANGE))
            modelState.AddModelError(StongTypeHelpers.GetPropertyName((Post p) => p.BodyMarkup),
                "Please make sure the post is between {0} characters in length".With(BODY_LENGTH_RANGE));

        return modelState;
    }
}
    public static Post GetNewPost(string title, string bodyMarkup, DateTime posted)
    {
        var post = new Post(0, title, bodyMarkup, posted, new List<Comment>());
        var fieldLengthSpec = new PostFieldLengthSpecification();

        if (fieldLengthSpec.IsSatisfiedBy(post))
            return post;
        else
            throw new InvariantException(post, fieldLengthSpec.GetErrors(post));
    }
public class PostModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        if (bindingContext.ModelType == typeof(Post))
        {
            try
            {
                // Create Post
                return base.BindModel(controllerContext, bindingContext);
            }
            catch (InvariantException ie)
            {
                // If invalid, add errors from factory to ModelState
                bindingContext.ModelState.AddNewErrors(ie.ModelState);
                bindingContext.ModelState.AddValuesFor<Post>(bindingContext.ValueProvider);
                return ie.FailingObject;
            }
        }
公共类PostFieldLength规范:I规范
{
私有常量字符串标题\u长度\u范围=“5-100”;
私有常量字符串正文\u长度\u范围=“20-10000”;
公共图书馆(邮政)满意
{
返回此.GetErrors(post).IsValid;
}
公共ModelStateDictionary GetErrors(Post Post)
{
ModelStateDictionary modelState=新的ModelStateDictionary();
如果(!post.Title.Trim().Length.在(Title\u Length\u范围内))
modelState.AddModelError(StongTypeHelpers.GetPropertyName((Post p)=>p.Title),
“请确保标题长度在{0}个字符之间”。使用(title_length_RANGE));
如果(!post.BodyMarkup.Trim().Length.在(BODY\u Length\u范围内))
modelState.AddModelError(StongTypeHelpers.GetPropertyName((Post p)=>p.BodyMarkup),
“请确保帖子长度在{0}个字符之间”。使用(BODY_length_RANGE));
返回模型状态;
}
}
工厂如何从不创建无效实例的示例,而是引发异常并为UI存放消息:

public class InvariantException : MyAppException
{
    public object FailingObject = null;
    public ModelStateDictionary ModelState = new ModelStateDictionary();


    public InvariantException() { }

    public InvariantException(object failingObject, ModelStateDictionary messages)
    {
        this.FailingObject = failingObject;
        this.ModelState = messages;
    }

    public InvariantException(object failingObject, ModelStateDictionary messages,
        Exception innerException)
        : base("refer to ModelState", innerException)
    {
        this.FailingObject = failingObject;
        this.ModelState = messages;
    }
}
public class PostFieldLengthSpecification : ISpecification<Post>
{
    private  const string TITLE_LENGTH_RANGE = "5-100";
    private  const string BODY_LENGTH_RANGE = "20-10000";


    public bool IsSatisfiedBy(Post post)
    {
        return this.GetErrors(post).IsValid;
    }


    public ModelStateDictionary GetErrors(Post post)
    {
        ModelStateDictionary modelState = new ModelStateDictionary();

        if (!post.Title.Trim().Length.Within(TITLE_LENGTH_RANGE))
            modelState.AddModelError(StongTypeHelpers.GetPropertyName((Post p) => p.Title),
                "Please make sure the title is between {0} characters in length".With(TITLE_LENGTH_RANGE));

        if (!post.BodyMarkup.Trim().Length.Within(BODY_LENGTH_RANGE))
            modelState.AddModelError(StongTypeHelpers.GetPropertyName((Post p) => p.BodyMarkup),
                "Please make sure the post is between {0} characters in length".With(BODY_LENGTH_RANGE));

        return modelState;
    }
}
    public static Post GetNewPost(string title, string bodyMarkup, DateTime posted)
    {
        var post = new Post(0, title, bodyMarkup, posted, new List<Comment>());
        var fieldLengthSpec = new PostFieldLengthSpecification();

        if (fieldLengthSpec.IsSatisfiedBy(post))
            return post;
        else
            throw new InvariantException(post, fieldLengthSpec.GetErrors(post));
    }
public class PostModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        if (bindingContext.ModelType == typeof(Post))
        {
            try
            {
                // Create Post
                return base.BindModel(controllerContext, bindingContext);
            }
            catch (InvariantException ie)
            {
                // If invalid, add errors from factory to ModelState
                bindingContext.ModelState.AddNewErrors(ie.ModelState);
                bindingContext.ModelState.AddValuesFor<Post>(bindingContext.ValueProvider);
                return ie.FailingObject;
            }
        }
publicstaticpost-GetNewPost(字符串标题、字符串bodyMarkup、DateTime-Post)
{
var post=new post(0,title,bodyMarkup,posted,new List());
var fieldLengthSpec=新的PostFieldLengthSpecification();
if(现场长度规格符合(post))
回程站;
其他的
抛出新的不变量异常(post,fieldLengthSpec.GetErrors(post));
}
最后,一个自定义模型绑定器的示例,用于捕获所述异常并将“无效对象”传递回操作,并显示错误消息:

public class InvariantException : MyAppException
{
    public object FailingObject = null;
    public ModelStateDictionary ModelState = new ModelStateDictionary();


    public InvariantException() { }

    public InvariantException(object failingObject, ModelStateDictionary messages)
    {
        this.FailingObject = failingObject;
        this.ModelState = messages;
    }

    public InvariantException(object failingObject, ModelStateDictionary messages,
        Exception innerException)
        : base("refer to ModelState", innerException)
    {
        this.FailingObject = failingObject;
        this.ModelState = messages;
    }
}
public class PostFieldLengthSpecification : ISpecification<Post>
{
    private  const string TITLE_LENGTH_RANGE = "5-100";
    private  const string BODY_LENGTH_RANGE = "20-10000";


    public bool IsSatisfiedBy(Post post)
    {
        return this.GetErrors(post).IsValid;
    }


    public ModelStateDictionary GetErrors(Post post)
    {
        ModelStateDictionary modelState = new ModelStateDictionary();

        if (!post.Title.Trim().Length.Within(TITLE_LENGTH_RANGE))
            modelState.AddModelError(StongTypeHelpers.GetPropertyName((Post p) => p.Title),
                "Please make sure the title is between {0} characters in length".With(TITLE_LENGTH_RANGE));

        if (!post.BodyMarkup.Trim().Length.Within(BODY_LENGTH_RANGE))
            modelState.AddModelError(StongTypeHelpers.GetPropertyName((Post p) => p.BodyMarkup),
                "Please make sure the post is between {0} characters in length".With(BODY_LENGTH_RANGE));

        return modelState;
    }
}
    public static Post GetNewPost(string title, string bodyMarkup, DateTime posted)
    {
        var post = new Post(0, title, bodyMarkup, posted, new List<Comment>());
        var fieldLengthSpec = new PostFieldLengthSpecification();

        if (fieldLengthSpec.IsSatisfiedBy(post))
            return post;
        else
            throw new InvariantException(post, fieldLengthSpec.GetErrors(post));
    }
public class PostModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        if (bindingContext.ModelType == typeof(Post))
        {
            try
            {
                // Create Post
                return base.BindModel(controllerContext, bindingContext);
            }
            catch (InvariantException ie)
            {
                // If invalid, add errors from factory to ModelState
                bindingContext.ModelState.AddNewErrors(ie.ModelState);
                bindingContext.ModelState.AddValuesFor<Post>(bindingContext.ValueProvider);
                return ie.FailingObject;
            }
        }
公共类PostModelBinder:DefaultModelBinder
{
公共重写对象BindModel(ControllerContext ControllerContext,ModelBindingContext bindingContext)
{
if(bindingContext.ModelType==typeof(Post))
{
尝试
{
//创建帖子
返回base.BindModel(controllerContext、bindingContext);
}
捕获(不变量异常)
{
//如果无效,请将错误从factory添加到ModelState
bindingContext.ModelState.AddNewErrors(即ModelState);
bindingContext.ModelState.AddValuesFor(bindingContext.ValueProvider);
返回ie.FailingObject;
}
}

希望这能有所帮助。

我还没有阅读链接的文档,但我有一个简单的例子,在这个例子中,我提出了异常,以响应无法满足不变量的情况。假设我正在创建一个实例,它由于某种原因是“无效”的,让我们假设用户输入错误。与其让我的实体处于无效状态(在DDD中是“否”),不如让系统“验证”它,它在创建时抛出异常。相关的“验证消息”(针对用户)是从未满足的同一规范实例中提取的,并且我的派生异常包含UI需要的值

不变量异常的示例:

public class InvariantException : MyAppException
{
    public object FailingObject = null;
    public ModelStateDictionary ModelState = new ModelStateDictionary();


    public InvariantException() { }

    public InvariantException(object failingObject, ModelStateDictionary messages)
    {
        this.FailingObject = failingObject;
        this.ModelState = messages;
    }

    public InvariantException(object failingObject, ModelStateDictionary messages,
        Exception innerException)
        : base("refer to ModelState", innerException)
    {
        this.FailingObject = failingObject;
        this.ModelState = messages;
    }
}
public class PostFieldLengthSpecification : ISpecification<Post>
{
    private  const string TITLE_LENGTH_RANGE = "5-100";
    private  const string BODY_LENGTH_RANGE = "20-10000";


    public bool IsSatisfiedBy(Post post)
    {
        return this.GetErrors(post).IsValid;
    }


    public ModelStateDictionary GetErrors(Post post)
    {
        ModelStateDictionary modelState = new ModelStateDictionary();

        if (!post.Title.Trim().Length.Within(TITLE_LENGTH_RANGE))
            modelState.AddModelError(StongTypeHelpers.GetPropertyName((Post p) => p.Title),
                "Please make sure the title is between {0} characters in length".With(TITLE_LENGTH_RANGE));

        if (!post.BodyMarkup.Trim().Length.Within(BODY_LENGTH_RANGE))
            modelState.AddModelError(StongTypeHelpers.GetPropertyName((Post p) => p.BodyMarkup),
                "Please make sure the post is between {0} characters in length".With(BODY_LENGTH_RANGE));

        return modelState;
    }
}
    public static Post GetNewPost(string title, string bodyMarkup, DateTime posted)
    {
        var post = new Post(0, title, bodyMarkup, posted, new List<Comment>());
        var fieldLengthSpec = new PostFieldLengthSpecification();

        if (fieldLengthSpec.IsSatisfiedBy(post))
            return post;
        else
            throw new InvariantException(post, fieldLengthSpec.GetErrors(post));
    }
public class PostModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        if (bindingContext.ModelType == typeof(Post))
        {
            try
            {
                // Create Post
                return base.BindModel(controllerContext, bindingContext);
            }
            catch (InvariantException ie)
            {
                // If invalid, add errors from factory to ModelState
                bindingContext.ModelState.AddNewErrors(ie.ModelState);
                bindingContext.ModelState.AddValuesFor<Post>(bindingContext.ValueProvider);
                return ie.FailingObject;
            }
        }
为用户/UI返回相关“验证消息”的规范示例:

public class InvariantException : MyAppException
{
    public object FailingObject = null;
    public ModelStateDictionary ModelState = new ModelStateDictionary();


    public InvariantException() { }

    public InvariantException(object failingObject, ModelStateDictionary messages)
    {
        this.FailingObject = failingObject;
        this.ModelState = messages;
    }

    public InvariantException(object failingObject, ModelStateDictionary messages,
        Exception innerException)
        : base("refer to ModelState", innerException)
    {
        this.FailingObject = failingObject;
        this.ModelState = messages;
    }
}
public class PostFieldLengthSpecification : ISpecification<Post>
{
    private  const string TITLE_LENGTH_RANGE = "5-100";
    private  const string BODY_LENGTH_RANGE = "20-10000";


    public bool IsSatisfiedBy(Post post)
    {
        return this.GetErrors(post).IsValid;
    }


    public ModelStateDictionary GetErrors(Post post)
    {
        ModelStateDictionary modelState = new ModelStateDictionary();

        if (!post.Title.Trim().Length.Within(TITLE_LENGTH_RANGE))
            modelState.AddModelError(StongTypeHelpers.GetPropertyName((Post p) => p.Title),
                "Please make sure the title is between {0} characters in length".With(TITLE_LENGTH_RANGE));

        if (!post.BodyMarkup.Trim().Length.Within(BODY_LENGTH_RANGE))
            modelState.AddModelError(StongTypeHelpers.GetPropertyName((Post p) => p.BodyMarkup),
                "Please make sure the post is between {0} characters in length".With(BODY_LENGTH_RANGE));

        return modelState;
    }
}
    public static Post GetNewPost(string title, string bodyMarkup, DateTime posted)
    {
        var post = new Post(0, title, bodyMarkup, posted, new List<Comment>());
        var fieldLengthSpec = new PostFieldLengthSpecification();

        if (fieldLengthSpec.IsSatisfiedBy(post))
            return post;
        else
            throw new InvariantException(post, fieldLengthSpec.GetErrors(post));
    }
public class PostModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        if (bindingContext.ModelType == typeof(Post))
        {
            try
            {
                // Create Post
                return base.BindModel(controllerContext, bindingContext);
            }
            catch (InvariantException ie)
            {
                // If invalid, add errors from factory to ModelState
                bindingContext.ModelState.AddNewErrors(ie.ModelState);
                bindingContext.ModelState.AddValuesFor<Post>(bindingContext.ValueProvider);
                return ie.FailingObject;
            }
        }
公共类PostFieldLength规范:I规范
{
私有常量字符串标题\u长度\u范围=“5-100”;
私有常量字符串正文\u长度\u范围=“20-10000”;
公共图书馆(邮政)满意
{
返回此.GetErrors(post).IsValid;
}
公共ModelStateDictionary GetErrors(Post Post)
{
ModelStateDictionary modelState=新的ModelStateDictionary();
如果(!post.Title.Trim().Length.在(Title\u Length\u范围内))
modelState.AddModelError(StongTypeHelpers.GetPropertyName((Post p)=>p.Title),
“请确保标题长度在{0}个字符之间”。使用(title_length_RANGE));
如果(!post.BodyMarkup.Trim().Length.在(BODY\u Length\u范围内))
modelState.AddModelError(StongTypeHelpers.GetPropertyName((Post p)=>p.BodyMarkup),
“请确保帖子长度在{0}个字符之间”。使用(BODY_length_RANGE));
返回模型状态;
}
}
工厂如何从不创建无效实例的示例,而是引发异常并为UI存放消息:

public class InvariantException : MyAppException
{
    public object FailingObject = null;
    public ModelStateDictionary ModelState = new ModelStateDictionary();


    public InvariantException() { }

    public InvariantException(object failingObject, ModelStateDictionary messages)
    {
        this.FailingObject = failingObject;
        this.ModelState = messages;
    }

    public InvariantException(object failingObject, ModelStateDictionary messages,
        Exception innerException)
        : base("refer to ModelState", innerException)
    {
        this.FailingObject = failingObject;
        this.ModelState = messages;
    }
}
public class PostFieldLengthSpecification : ISpecification<Post>
{
    private  const string TITLE_LENGTH_RANGE = "5-100";
    private  const string BODY_LENGTH_RANGE = "20-10000";


    public bool IsSatisfiedBy(Post post)
    {
        return this.GetErrors(post).IsValid;
    }


    public ModelStateDictionary GetErrors(Post post)
    {
        ModelStateDictionary modelState = new ModelStateDictionary();

        if (!post.Title.Trim().Length.Within(TITLE_LENGTH_RANGE))
            modelState.AddModelError(StongTypeHelpers.GetPropertyName((Post p) => p.Title),
                "Please make sure the title is between {0} characters in length".With(TITLE_LENGTH_RANGE));

        if (!post.BodyMarkup.Trim().Length.Within(BODY_LENGTH_RANGE))
            modelState.AddModelError(StongTypeHelpers.GetPropertyName((Post p) => p.BodyMarkup),
                "Please make sure the post is between {0} characters in length".With(BODY_LENGTH_RANGE));

        return modelState;
    }
}
    public static Post GetNewPost(string title, string bodyMarkup, DateTime posted)
    {
        var post = new Post(0, title, bodyMarkup, posted, new List<Comment>());
        var fieldLengthSpec = new PostFieldLengthSpecification();

        if (fieldLengthSpec.IsSatisfiedBy(post))
            return post;
        else
            throw new InvariantException(post, fieldLengthSpec.GetErrors(post));
    }
public class PostModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        if (bindingContext.ModelType == typeof(Post))
        {
            try
            {
                // Create Post
                return base.BindModel(controllerContext, bindingContext);
            }
            catch (InvariantException ie)
            {
                // If invalid, add errors from factory to ModelState
                bindingContext.ModelState.AddNewErrors(ie.ModelState);
                bindingContext.ModelState.AddValuesFor<Post>(bindingContext.ValueProvider);
                return ie.FailingObject;
            }
        }
publicstaticpost-GetNewPost(字符串标题、字符串bodyMarkup、DateTime-Post)
{
var post=new post(0,title,bodyMarkup,posted,new List)()