How to reuse part of model for multiple pages

Viewed 140

I have an existing asp.net core razor page that records events for our Security Team. They would like to record Lost and Found events as well, but have them kept separate from the Security events. I would like to reuse the same database table and differentiate the record (AppType). Although the two apps share many similarities, Lost and Found does not use all of the same properties (i.e. L&F will not use SubjectDOB but it is required in the Security model. This will cause (!ModelState.IsValid) to return false. What is the best way to reuse the SecurityLog model for Lost and Found for only the properties that I need? Perhaps I need to split the classes up?

public class SecurityLog
{        
    public string AppType { get; set; }
    
    [Required]
    [Display(Name = "Subject's First Name")]
    public string SubjectFirst { get; set; }

    [Required]
    [Display(Name = "Subject's Last Name")]
    public string SubjectLast { get; set; }

    [Required]
    [Display(Name = "Subject's B#/DOB")]
    public string SubjectDOB { get; set; }

    [Display(Name = "Entered By")]
    public string EnteredBy { get; set; }
    
    etc...
 }

I've tried removing subjectDOB from the model but this does not work b/c it is required.

public async Task<IActionResult> OnPostAsync()
{
     ModelState.Remove("SubjectDOB");                        

     if (!ModelState.IsValid)
     {
        return Page();
     }
}
2 Answers

ModelState.Remove(keyname); should work as expected. Be sure the key name is correct.

Here is a sample you could follow:

Index.cshtml:

@page
@model IndexModel
<form method="post">
    <input asp-for="SecurityLog.EnteredBy" />
    <input asp-for="SecurityLog.SubjectFirst" />
    <input asp-for="SecurityLog.SubjectLast" />
    <input asp-for="SecurityLog.SubjectDOB" />
    <input type="submit" />
</form>  

Index.cshtml.cs:

public class IndexModel : PageModel
{
    public SecurityLog SecurityLog { get; set; }
    public async Task<IActionResult> OnPostAsync([Bind(Prefix = "SecurityLog")]SecurityLog model)
    {
        ModelState.Remove("SecurityLog.SubjectDOB");

        if (!ModelState.IsValid)
        {
            return Page();
        }
        return Page();
    }
    public async Task<IActionResult> OnGetAsync()
    {
        return Page();
    }
}

Abstraction can be used to extract all of the base properties into a separate reusable class.

public class BaseSecurityLog
{        
    public string AppType { get; set; }

    [Required]
    [Display(Name = "Subject's First Name")]
    public string SubjectFirst { get; set; }

    [Required]
    [Display(Name = "Subject's Last Name")]
    public string SubjectLast { get; set; }

    [Display(Name = "Entered By")]
    public string EnteredBy { get; set; }
}

public class SecurityLog : BaseSecurityLog
{
    [Required]
    [Display(Name = "Subject's B#/DOB")]
    public string SubjectDOB { get; set; }
}
Related