1

I have an action method which outputs a model which has multiple sub models. In one of the sub model I have some additional properties which are not required in my view.

Sub model- ProjectModel-

[Required(ErrorMessage = "*")]
public int Id { get; set; }
[Required(ErrorMessage = "*")]
public int SectorDivisionId { get; set; }
[Required(ErrorMessage = "*")]
[StringLength(250, ErrorMessage = "Project name should not be more than 250 characters.")]
public string Program { get; set; }

[Required(ErrorMessage = "*")]
[StringLength(25, ErrorMessage = "Project number should not be more than 25 characters.")]
public string ProjectNumber { get; set; }

public string WorkPackage { get; set; }

public string WorkPackageType { get; set; }

[Required(ErrorMessage = "*")]
public DateTime StartDate { get; set; }
[Required(ErrorMessage = "*")]
public DateTime EndDate { get; set; }
public int ProjectDirectorId { get; set; }

So while initializing the sub model to my main model I am only using those properties which I need as shown below.

model.ProjectInfo = new ProjectModel()
{
    Id = projectId,
    ProjectNumber = prj.p.ProjectNumber,
    Director = prj.Director,
    Program = prj.p.Program,
    StartDate = prj.p.StartDate,
    EndDate = prj.p.EndDate,
    ProjectReviewPeriodList = projectReviewPeriodList.AsEnumerable().
                                Select(o => new ProjectReviewPeriodModel
                                {
                                    Id = o.Id,
                                    ProjectReviewTypeId = o.ProjectReviewTypeId,
                                    ProjectId = o.ProjectId,
                                    ReviewPeriod = o.ReviewPeriod,
                                    ReviewPeriodDate = o.ReviewPeriodDate                                                    
                                }).ToList()
};

Now, while posting the form I have an action filter at global level which validates the Model. The validation (ModelState.IsValid) fails for some of the fields from the sub model which I haven't initialized as per my needs.

I thought of two options-

  • Using ModelState.Remove(<PropertyName>) to skip validation. This is not possible as I am using a global level action filter.
  • Create a new view model

Is there any other way of doing this, preferably in the action method level?

Please let me know if any doubts or I can explain it more clearly.

Thanks.

11
  • 1
    Your editing data, so as always, use a view model (and that view model will contain only those properties you need in the view) Commented Jan 29, 2018 at 11:21
  • @StephenMuecke Yes, but in that case I will have to copy a lot of fields and it can cause duplication in future for every property I add/remove in future. Is there any alternate solution? Commented Jan 29, 2018 at 11:24
  • Use a custom ActionFilter, override OnActionExecuting and call modelState["ProjectModel"].Errors.Clear(); Commented Jan 29, 2018 at 11:25
  • @IvanZaruba Can I use both the custom filter and the inherited filter? Or will it conflict/override- modelState["ProjectModel"].Errors.Clear(); Commented Jan 29, 2018 at 11:28
  • Yet another thought - [Bind(Exclude="ProjectModel")] attribute Commented Jan 29, 2018 at 11:29

2 Answers 2

1

The clean way would be to use different ViewModels for different usecases.

That being said, you can implement the validation logic with IValidatableObject instead of using Data Annotations attributes.

Introduce a flag into the ViewModel that indicates the usecase, e.g. IsEditUsecase. Set this flag somewhere where you know the usecase, e.g. in the controller.

Then only perform the validations that are needed for this usecase.

public class ProjectModel : IValidatableObject {

    public bool IsEditUsecase { get; set; }

    [Required(ErrorMessage = "*")] // required for every usecase
    public int Id { get; set; }

    // no [Required] and [StringLength] attributes 
    // because only required in some of the usecases
    public string Program { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
         // validation that occurs only in Edit usecase
         if (IsEditUsecase) {

             // Validate "Program" property
             if (string.IsNullOrWhiteSpace(Program)) {
                 yield return new ValidationResult(
                        "Program is required",
                        new[] { "Program" }
                 );
             } 
             else if (Program.Length > 250) {
                 yield return new ValidationResult(
                     "Project name should not be more than 250 characters.",
                     new[] { "Program" }
                 );
             }

             // validate other properties for Edit usecase ...
         }

         // validate other usecases ...
    }
}
Sign up to request clarification or add additional context in comments.

Comments

0

As a dirty hack, I have added hidden fields in my razor page for all those properties which caused ModelState validation error. Basically I added some default values for the hidden fields and it works fine now. Not recommended though but it was a quick fix.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.