系统.MissingMethodException:没有为该对象定义无参数构造函数

本文关键字:定义 对象 参数 构造函数 MissingMethodException 系统 | 更新日期: 2023-09-27 18:10:20

我在MVC 2 web应用程序上间歇性地得到这个错误。我的模型没有无参数构造函数,它们看起来像这样:

    public AddParentModel(ITracktionDataLayer dataLayer, MessagePasser messager, AuthUserHelper authUser)
    {
        _model = new PersonAddEditModel(messager, dataLayer, authUser, null);
    }

我应该注意到我的控制器确实有无参数构造函数。personadditmodel不直接暴露给MVC。AddParentModel的存在只是为了使MVC绑定更容易。

由于AddParentModel(和MVC正在使用的所有其他模型)存在于服务器上,我可以使它们无参数,尽管这会使我的测试方法有点混乱。奇怪的是它间歇性地发生。我希望这样的问题持续发生,但这绝对不是情况-我只是得到ELMAH给我发电子邮件每隔一天左右,一些不幸的用户得到这个错误。

我想知道我有什么选择。我认为解决这个问题最简单的方法是创建一个构造函数重载,它只将这些参数设置为默认对象(我现在可能会这样做,只是为了解决手头的问题,但我觉得这样做很脏),但我希望从人们那里得到正确处理这个问题的方法。我对MVC比较陌生。提前感谢!

EDIT:我想在我的[HttpPost]方法中添加处理完成的地方,即使我在视图上使用MVC的编辑模型,我也会收到一个FormCollection并使用它来更新模型,而不是让MVC直接编辑模型。

    /// <summary>
    /// Add this person, then go to the next page where more people can be added.
    /// </summary>
    /// <param name="model"></param>
    /// <returns></returns>
    [HttpPost]
    public ActionResult Index(FormCollection fc, HttpPostedFileWrapper upload) {
        Uri requestUri = !Request.Url.ToString().Contains("/127.0.0.1/") ? Request.Url : new Uri("...");
        MessagePasser messager = new MessagePasser();
        ITracktionDataLayer dataLayer = DataFactory.GetDataLayer();
        AuthUserHelper user = AuthUserHelper.AnonymousWebUserFrom(dataLayer, requestUri);
        AddParentModel model = new AddParentModel(dataLayer, messager, user);
        if (TryUpdateModel(model, fc) && ModelState.IsValid)
        {
        ...

我还意识到,对于一些模型,我不能创建无参数构造函数,因为一些模型需要在我的数据层、消息传递层和经过身份验证的用户之上和之外的两个额外的原语。

系统.MissingMethodException:没有为该对象定义无参数构造函数

我不能使用依赖注入来解决这个问题,因为我请求的额外参数依赖于构造函数中的用户信息。我的构造函数接受IDataLayer, MessagePasser和AuthUserHelper,这对于所有模型都是常见的,但我也要求两个int id,它依赖于一些隐藏的输入字段或查询字符串参数。

因此,我将把模型的属性拆分为它自己的类(模型)和实际的处理,例如加载和保存到服务类中。模型只是一个属性包,可以有一个无参数的构造函数,而调用服务类来填充和保存数据。我希望这个答案能帮助到你。

之前我有:

public class EditFamilyMemberModel
{

    #region Constructor
    public EditFamilyMemberModel(ITracktionDataLayer dataLayer, MessagePasser messager, AuthUserHelper authUser, int originalPersonID, int familyMemberID)
    {
        _dataLayer = dataLayer;
        _originalPerson = new PersonAddEditModel(messager, dataLayer, authUser, originalPersonID);
        _model = new PersonAddEditModel(messager, dataLayer, authUser, familyMemberID);
        _grades = _dataLayer.GetGradesForOrganization(authUser.OrganizationID, _model.Person.Grade, true).ToArray();
    }
    #endregion
    #region Private
    ITracktionDataLayer _dataLayer;
    PersonAddEditModel _originalPerson;
    PersonAddEditModel _model;
    IList<Grade> _grades;
    #endregion
    #region Properties
    #region Read Only
    public Person Person
    {
        get { return _model.Person; }
    }
    public AuthUserHelper AuthUser
    {
        get { return _model.AuthUser; }
    }
    public IList<School> Schools
    {
        get { return _model.Schools; }
    }
    public IList<ContactType> ContactTypes
    {
        get { return _model.ContactTypes; }
    }
    public IList<string> Genders
    {
        get { return _model.Genders; }
    }
    public IList<Grade> Grades
    {
        get { return /*_model.Grades;*/ _grades; }
    }
    public IList<USState> USStates
    {
        get { return _model.USStates; }
    }
    public IList<PersonType> PersonTypes
    {
        get { return _model.PersonTypes; }
    }
    public IList<FamilyRole> FamilyRoles
    {
        get { return _model.FamilyRoles; }
    }
    #endregion
    [Required]
    [StringLength(100)]
    public string Address
    {
        get { return _model.Person.Address; }
        set { _model.Person.Address = value; }
    }

    [StringLength(100)]
    public string Address2
    {
        get { return _model.Person.Address2; }
        set { _model.Person.Address2 = value; }
    }
    [Required]
    [StringLength(50)]
    public string City
    {
        get { return _model.Person.City; }
        set { _model.Person.City = value; }
    }
    [Required]
    [StringLength(50)]
    public string State
    {
        get { return _model.Person.State; }
        set { _model.Person.State = value; }
    }
    [Required]
    [StringLength(50)]
    public string Zip
    {
        get { return _model.Person.Zip; }
        set { _model.Person.Zip = value; }
    }
    [DataType(DataType.Date)]
    //[Required]
    public DateTime? DOB
    {
        get { return _model.Person.DOB; }
        set { _model.Person.DOB = value; }
    }
    [Required]
    public string Gender
    {
        get { return _model.Person.Gender; }
        set { _model.Person.Gender = value; }
    }
    [Required]
    public string FirstName
    {
        get { return _model.Person.FirstName; }
        set { _model.Person.FirstName = value; }
    }
    [Required]
    public string LastName
    {
        get { return _model.Person.LastName; }
        set { _model.Person.LastName = value; }
    }
    public int? SchoolID
    {
        get { return _model.Person.SchoolID; }
        set { _model.Person.SchoolID = value; }
    }
    public int? GradeID
    {
        get { return _model.Person.Grade; }
        set { _model.Person.Grade = value; }
    }
    public string SpecialNeedsDescription
    {
        get { return _model.Person.SpecialNeedsDescription; }
        set { _model.Person.SpecialNeedsDescription = value; }
    }
    public string SpecialNeedsSummary
    {
        get { return _model.Person.SpecialNeedsSummary; }
        set { _model.Person.SpecialNeedsSummary = value; }
    }
    public byte[] PictureData
    {
        get;
        set;
    }
    public string PictureAction
    {
        get;
        set;
    }

    #region Membership
    [Display(Name = "User Name")]
    [DisplayName("User Name")]
    [UniqueUserName(ErrorMessage = "The user name specified is already in use, please choose another user name.")]
    public string Username { get; set; }
    [Display(Name = "Password")]
    [DisplayName("Enter a password")]
    [StringLength(50, MinimumLength = 6, ErrorMessage = "Password must be at least 6 characters long.")]
    public string Password { get; set; }
    [DisplayName("Confirm Password")]
    [StringLength(50, MinimumLength = 6)]
    public string PasswordConfirm { get; set; }
    #endregion
    #region Abstracted Contact Methods
    /// <summary>
    /// When adding someone, this represents the phone number contact record.
    /// </summary>
    [Display(Name = "Home Phone Number")]
    [DisplayName("Home Phone Number")]
    [USPhoneNumber]
    //[Required]
    public string HomePhoneNumber
    {
        get { return _model.HomePhone; }
        set { _model.HomePhone = value; }
    }
    /// <summary>
    /// When adding someone, this represents the phone number contact record.
    /// </summary>
    [Display(Name = "Cell Phone Number")]
    [DisplayName("Cell Phone Number")]
    [USPhoneNumber]
    //[Required]
    public string CellPhoneNumber
    {
        get { return _model.PersonalCell; }
        set { _model.PersonalCell = value; }
    }
    /// <summary>
    /// When adding someone, this represents the email address contact record.
    /// </summary>
    [Display(Name = "Email Address")]
    [DisplayName("Email Address")]
    //[Required] -- Some parents dont have email addresses
    [UniqueEmailAddress(ErrorMessage = "The email address was already found in our system, please sign in or use another email.")]
    [Email(ErrorMessage = "The email address specified isn't an email address.")]
    public string EmailAddress
    {
        get { return _model.EmailAddress; }
        set { _model.EmailAddress = value; }
    }
    #endregion
    #endregion
    #region Logic
    public void SaveChanges()
    {
        _model.Person.ChangedTimeStamp = DateTime.Now;
        _model.Person.ChangedBy = -1;
        // If we have a valid home #, add it
        if (!string.IsNullOrWhiteSpace(HomePhoneNumber))
            _model.HomePhone = HomePhoneNumber;
        // If we have a valid cell #, add it
        if (!string.IsNullOrWhiteSpace(CellPhoneNumber))
            _model.PersonalCell = CellPhoneNumber;
        // If we have a valid email, add it
        if (!string.IsNullOrWhiteSpace(EmailAddress))
            _model.EmailAddress = EmailAddress;
        // Some fields may have 'not applicable'; blank them
        _model.Person.SpecialNeedsDescription = _model.Person.SpecialNeedsDescription.NormalizeNotApplicable().NullIfEmptyOrWhitespace();
        _model.Person.SpecialNeedsSummary = _model.Person.SpecialNeedsSummary.NormalizeNotApplicable().NullIfEmptyOrWhitespace();
        // Names of people should be proper case if they're all entered in lowercase
        _model.Person.FirstName = _model.Person.FirstName.NormalizeName();
        _model.Person.LastName = _model.Person.LastName.NormalizeName();
        if (PictureData != null && (PictureAction == "replace" || (PictureAction ?? "") == ""))
        {
            // Replace just adds, it does not remove the old picture.
            Photo pic = PhotoHandling.GetPhotoEntityFromBytes(PictureData);
            pic.ROWGUID = Guid.NewGuid();
            pic.OrganizationID = _model.AuthUser.OrganizationID;
            pic.CreationTimestamp = DateTime.Now;
            pic.Deleted = false;
            _model.AddNewPhoto(pic);
            _model.Person.Avatar = pic.ROWGUID;
        }
        else if (PictureAction == "remove" && _model.Person.Avatar.HasValue)
        {
            var pic = _model.Person.Photos.SingleOrDefault(p => p.ROWGUID == _model.Person.Avatar.Value);
            if (pic != null)
            {
                pic.Deleted = true;
                _model.Person.Avatar = null;
            }
        }
        _model.SaveChanges();
    }
    #endregion
}

现在我把它分成了:

public class EditFamilyMemberModel
{
    public EditFamilyMemberModel() { }
    #region Properties
    [Required]
    [StringLength(100)]
    public string Address { get; set; }
    [StringLength(100)]
    public string Address2 { get; set; }
    [Required]
    [StringLength(50)]
    public string City { get; set; }
    [Required]
    [StringLength(50)]
    public string State { get; set; }
    [Required]
    [StringLength(50)]
    public string Zip { get; set; }
    [DataType(DataType.Date)]
    //[Required]
    public DateTime? DOB { get; set; }
    [Required]
    public string Gender { get; set; }
    [Required]
    public string FirstName { get; set; }
    [Required]
    public string LastName { get; set; }
    public int? SchoolID { get; set; }
    public int? GradeID { get; set; }
    public string SpecialNeedsDescription { get; set; }
    public string SpecialNeedsSummary { get; set; }
    public byte[] PictureData { get; set; }
    public string PictureAction { get; set; }
    #region Membership
    [Display(Name = "User Name")]
    [DisplayName("User Name")]
    [UniqueUserName(ErrorMessage = "The user name specified is already in use, please choose another user name.")]
    public string Username { get; set; }
    [Display(Name = "Password")]
    [DisplayName("Enter a password")]
    [StringLength(50, MinimumLength = 6, ErrorMessage = "Password must be at least 6 characters long.")]
    public string Password { get; set; }
    [DisplayName("Confirm Password")]
    [StringLength(50, MinimumLength = 6)]
    public string PasswordConfirm { get; set; }
    #endregion
    #region Abstracted Contact Methods
    /// <summary>
    /// When adding someone, this represents the phone number contact record.
    /// </summary>
    [Display(Name = "Home Phone Number")]
    [DisplayName("Home Phone Number")]
    [USPhoneNumber]
    //[Required]
    public string HomePhoneNumber { get; set; }
    /// <summary>
    /// When adding someone, this represents the phone number contact record.
    /// </summary>
    [Display(Name = "Cell Phone Number")]
    [DisplayName("Cell Phone Number")]
    [USPhoneNumber]
    //[Required]
    public string CellPhoneNumber { get; set; }
    /// <summary>
    /// When adding someone, this represents the email address contact record.
    /// </summary>
    [Display(Name = "Email Address")]
    [DisplayName("Email Address")]
    //[Required] -- Some parents dont have email addresses
    //[UniqueEmailAddress(ErrorMessage = "The email address was already found in our system, please sign in or use another email.")]
    [Email(ErrorMessage = "The email address specified isn't an email address.")]
    public string EmailAddress { get; set; }
    #endregion
    #endregion
    #region Read-Only Properties
    public IList<School> Schools { get; internal set; }
    public IList<ContactType> ContactTypes { get; internal set; }
    public IList<string> Genders { get; internal set; }
    public IList<Grade> Grades { get; internal set; }
    public IList<USState> USStates { get; internal set; }
    public IList<PersonType> PersonTypes { get; internal set; }
    public IList<FamilyRole> FamilyRoles { get; internal set; }
    public Person Person { get; internal set; }
    #endregion
}
public class EditFamilyMemberService
{
    #region Constructor
    public EditFamilyMemberService(ITracktionDataLayer dataLayer, MessagePasser messager, AuthUserHelper authUser, int originalPersonID, int familyMemberID)
    {
        _dataLayer = dataLayer;
        _originalPerson = new PersonAddEditModel(messager, dataLayer, authUser, originalPersonID);
        _model = new PersonAddEditModel(messager, dataLayer, authUser, familyMemberID);
        _grades = _dataLayer.GetGradesForOrganization(authUser.OrganizationID, _model.Person.Grade, true).ToArray();
        Model = new EditFamilyMemberModel()
        {
            Address = _model.Person.Address,
            Address2 = _model.Person.Address2,
            CellPhoneNumber = _model.PersonalCell,
            City = _model.Person.City,
            ContactTypes = _model.ContactTypes,
            DOB = _model.Person.DOB,
            EmailAddress = _model.EmailAddress,
            FamilyRoles = _model.FamilyRoles,
            FirstName = _model.Person.FirstName,
            Gender = _model.Person.Gender,
            Genders = _model.Genders,
            GradeID = _model.Person.Grade,
            Grades = _model.Grades,
            HomePhoneNumber = _model.HomePhone,
            LastName = _model.Person.LastName,
            Password = null,
            PasswordConfirm = null,
            PersonTypes = _model.PersonTypes,
            PictureAction = null,
            PictureData = null,
            SchoolID = _model.Person.SchoolID,
            Schools = _model.Schools,
            SpecialNeedsDescription = _model.Person.SpecialNeedsDescription,
            SpecialNeedsSummary = _model.Person.SpecialNeedsSummary,
            State = _model.Person.State,
            Username = null,
            USStates = _model.USStates,
            Zip = _model.Person.Zip,
            Person = _model.Person
        };
    }
    #endregion
    #region Private
    ITracktionDataLayer _dataLayer;
    PersonAddEditModel _originalPerson;
    PersonAddEditModel _model;
    IList<Grade> _grades;
    #endregion
    #region Properties
    public EditFamilyMemberModel Model { get; internal set; }
    #region Read Only
    public Person Person
    {
        get { return _model.Person; }
    }
    public AuthUserHelper AuthUser
    {
        get { return _model.AuthUser; }
    }
    #endregion

    #endregion
    #region Logic
    public void SaveChanges()
    {
        _model.Person.ChangedTimeStamp = DateTime.Now;
        _model.Person.ChangedBy = -1;
        // If we have a valid home #, add it
        if (!string.IsNullOrWhiteSpace(Model.HomePhoneNumber))
            _model.HomePhone = Model.HomePhoneNumber;
        // If we have a valid cell #, add it
        if (!string.IsNullOrWhiteSpace(Model.CellPhoneNumber))
            _model.PersonalCell = Model.CellPhoneNumber;
        // If we have a valid email, add it
        if (!string.IsNullOrWhiteSpace(Model.EmailAddress))
            _model.EmailAddress = Model.EmailAddress;
        // Some fields may have 'not applicable'; blank them
        Model.SpecialNeedsDescription = Model.SpecialNeedsDescription.NormalizeNotApplicable().NullIfEmptyOrWhitespace();
        Model.SpecialNeedsSummary = Model.SpecialNeedsSummary.NormalizeNotApplicable().NullIfEmptyOrWhitespace();
        // Names of people should be proper case if they're all entered in lowercase
        Model.FirstName = Model.FirstName.NormalizeName();
        Model.LastName = Model.LastName.NormalizeName();
        // Save this extra information
        _model.Person.Address = Model.Address;
        _model.Person.Address2 = Model.Address2;
        _model.PersonalCell = Model.CellPhoneNumber;
        _model.Person.City = Model.City;
        _model.Person.DOB = Model.DOB;
        _model.EmailAddress = Model.EmailAddress;
        _model.Person.FirstName = Model.FirstName;
        _model.Person.Gender = Model.Gender;
        _model.Person.Grade = Model.GradeID;
        _model.HomePhone = Model.HomePhoneNumber;
        _model.Person.LastName = Model.LastName;
        _model.Person.SchoolID = Model.SchoolID;
        _model.Person.SpecialNeedsDescription = Model.SpecialNeedsDescription;
        _model.Person.SpecialNeedsSummary = Model.SpecialNeedsSummary;
        _model.Person.State = Model.State;
        _model.Person.Zip = Model.Zip;
        // Save picture data
        if (Model.PictureData != null && (Model.PictureAction == "replace" || (Model.PictureAction ?? "") == ""))
        {
            // Replace just adds, it does not remove the old picture.
            Photo pic = PhotoHandling.GetPhotoEntityFromBytes(Model.PictureData);
            pic.ROWGUID = Guid.NewGuid();
            pic.OrganizationID = _model.AuthUser.OrganizationID;
            pic.CreationTimestamp = DateTime.Now;
            pic.Deleted = false;
            _model.AddNewPhoto(pic);
            _model.Person.Avatar = pic.ROWGUID;
        }
        else if (Model.PictureAction == "remove" && _model.Person.Avatar.HasValue)
        {
            var pic = _model.Person.Photos.SingleOrDefault(p => p.ROWGUID == _model.Person.Avatar.Value);
            if (pic != null)
            {
                pic.Deleted = true;
                _model.Person.Avatar = null;
            }
        }
        _model.SaveChanges();
    }
    #endregion
}

模型本身不需要任何参数,不应该再抛出该错误。我非常喜欢将相关的逻辑和数据封装到一个类中,但是因为这只是一个围绕繁重的personaddedmodel的包装器,而且它只在MVC端使用,所以我可以处理这个问题。

如果有人对我刚刚发布的内容有任何意见或替代意见,我将洗耳恭听。