2011-10-04 135 views
0

我在我的MVC 2 Web应用程序中间歇性地收到此错误。我的模型没有参数构造函数,它们看起来就像这样:System.MissingMethodException:没有为此对象定义的无参数构造函数

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

我要指出,我的控制器都具有参数构造函数。 PersonAddEditModel不直接暴露给MVC。 AddParentModel仅用于使MVC绑定更容易。

由于AddParentModel(以及MVC使用的所有其他模型)都存在于服务器上,所以我可以使它们无参数,尽管这会让我的测试方法有点混乱。 关于这个的奇怪部分是它间歇性地发生。我期望这样的问题会一直发生,但事实绝非如此 - 我只是让ELMAH每隔一天向我发送一封电子邮件,以便一些不幸的用户得到此错误。

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

编辑:我想补充一点,在我的[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) 
     { 
     ... 

我也意识到,对于某些型号,我不能因为少数车型需要超出我的数据层,通讯层和身份验证的用户一对额外的原语创建一个参数的构造函数。

+1

请参阅http:// stackoverflow。com/questions/1355464/asp-net-mvc-no-parameterless-constructor-defined-this-object – Artomegus

回答

1

我不能使用依赖注入来解决这个问题,因为我正在请求额外的参数,这些参数依赖于构造函数中的用户信息。我的构造函数需要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 

} 

模型本身不需要任何构造函数参数,不应该抛出的错误了。我非常喜欢将相关的逻辑和数据封装到一个类中,但是因为这只是对繁重的PersonAddEditModel的封装,并且只用于MVC端,所以我可以处理这个问题。

如果有人对我刚刚发布的内容有任何意见或替代方案,我完全理解。

+0

谢谢,这只是解决了我与视图模型给出相同错误的问题。将我的IList属性更改为内部设置完成了这项工作! –

相关问题