Two models in same Razor View

Anjali Agarwal 1,531 Reputation points
2023-01-24T04:26:15.54+00:00

Hello All,

I have the following two model classes. I am using Database first approach to create the contaxt class:

public partial class EmployeeInfo

{

    public EmployeeInfo()

    {

        EmergencyInfos = new HashSet<EmergencyInfo>();

    }

    public int EmployeeInfoId { get; set; }

    public int PolicyYear { get; set; }

    public DateTime DateFormFilled { get; set; }

    public string EmployeeNumber { get; set; } = null!;

    public string LastName { get; set; } = null!;

    public string FirstName { get; set; } = null!;

    public string? MiddleName { get; set; }

	public virtual ICollection<EmergencyInfo> EmergencyInfos { get; set; }

  }

  

 public partial class EmergencyInfo

{

    public int EmergencyInfoId { get; set; }

    public int EmployeeInfoId { get; set; }

    public int ContactPriority { get; set; }

    public string LastName { get; set; } = null!;

    public string FirstName { get; set; } = null!;

    public string Relationship { get; set; } = null!;

    public string? HomePhone { get; set; }

    public string? WorkPhone { get; set; }

    public string? CellPhone { get; set; }

    public string EmailAddress { get; set; } = null!;

    public virtual EmployeeInfo EmployeeInfo { get; set; } = null!;

}

There could be multiple emergencyInfo for each employee. Right now, my Razor view looks like this:

@model WebApplication2.AckPackage.Models.EmployeeInfo

  <form asp-action="Create" asp-controller="EmployeeInfo">

        <div asp-validation-summary="ModelOnly" class="text-danger"></div>

        <div class="form-group">

            <label asp-for="PolicyYear" class="control-label"></label>

            <input asp-for="PolicyYear" class="form-control" />

            <span asp-validation-for="PolicyYear" class="text-danger"></span>

        </div>

        <div class="form-group">

            <label asp-for="DateFormFilled" class="control-label"></label>

            <input asp-for="DateFormFilled" class="form-control" />

            <span asp-validation-for="DateFormFilled" class="text-danger"></span>

        </div>

        <div class="form-group">

            <label asp-for="EmployeeNumber" class="control-label"></label>

            <input asp-for="EmployeeNumber" class="form-control" />

            <span asp-validation-for="EmployeeNumber" class="text-danger"></span>

        </div>

        <div class="form-group">

            <label asp-for="LastName" class="control-label"></label>

            <input asp-for="LastName" class="form-control" />

            <span asp-validation-for="LastName" class="text-danger"></span>

        </div>

        <div class="form-group">

            <label asp-for="FirstName" class="control-label"></label>

            <input asp-for="FirstName" class="form-control" />

            <span asp-validation-for="FirstName" class="text-danger"></span>

        </div>

        <div class="form-group">

            <label asp-for="MiddleName" class="control-label"></label>

            <input asp-for="MiddleName" class="form-control" />

            <span asp-validation-for="MiddleName" class="text-danger"></span>

        </div>

		     <div class="form-group">

            <input type="submit" value="Create" class="btn btn-primary" />

             </div>

			 

Below is my controller:

		
	 [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Edit(int id, [Bind("EmployeeInfoId,PolicyYear,DateFormFilled,EmployeeNumber,LastName,FirstName,MiddleName")] EmployeeInfo employeeInfo)
        {

            if (ModelState.IsValid)
            {
                try
                {
                    _context.Update(employeeInfo);
                    await _context.SaveChangesAsync();
                }
                catch (DbUpdateConcurrencyException)
                {
                    if (!EmployeeInfoExists(employeeInfo.EmployeeInfoId))
                    {
                        return NotFound();
                    }
                    else
                    {
                        throw;
                    }
                }
                return RedirectToAction(nameof(Index)		
          }	
 [HttpPost]

    [ValidateAntiForgeryToken]

    public async Task<IActionResult> Edit(int id, [Bind("EmployeeInfoId,PolicyYear,DateFormFilled,EmployeeNumber,LastName,FirstName,MiddleName")] EmployeeInfo employeeInfo)

    {

        if (ModelState.IsValid)

        {

            try

            {

                _context.Update(employeeInfo);

                await _context.SaveChangesAsync();

            }

            catch (DbUpdateConcurrencyException)

            {

                if (!EmployeeInfoExists(employeeInfo.EmployeeInfoId))

                {

                    return NotFound();

                }

                else

                {

                    throw;

                }

            }

            return RedirectToAction(nameof(Index)		

      }	

I want to put the input fields for emergency info on the same view with one submit button so that when the user clicks on the submit button, both emergencyInfo and emeployeeInfo gets saved in the database. Is it possible to accomplish that. I know about tuples, but they are using two buttons on the same page.

I want to use just one submit button that saves the employeeInfo and emergencyInfo.

I am very new to MVC-.net core and Razor view so any help will be highly appreciated.

I am using Database first approach and using Scaffolding to create my context class.

Any help will be highly appreciated.

Developer technologies ASP.NET ASP.NET Core
Developer technologies C#
0 comments No comments
{count} votes

Accepted answer
  1. Anonymous
    2023-01-24T07:19:22.3333333+00:00

    Hi @Anjali Agarwal

    	public virtual ICollection<EmergencyInfo> EmergencyInfos { get; set; }
    

    Since you have already configured one-to-many relationship between the employeeInfo and emergencyInfo model, in the EmployeeInfo Create or Edit page, you can display the emergencyInfo via the above Navigation property (EmergencyInfos).

    For example:

    In the Edit view page: Use for statement to loop through the EmergencyInfos, in this sample, I just test the EmailAddress property, you can add other properties. And note the name attribute, we will set its name based on the Page Model.

    @model WebApplication5.Models.EmployeeInfo
    
    @{
        ViewData["Title"] = "Edit";
    } 
    <h1>Edit</h1> 
    <div class="row">
        <div class="col-md-4">
            <form asp-action="Edit">
                <div asp-validation-summary="ModelOnly" class="text-danger"></div>
                <div class="form-group">
                    <label asp-for="EmployeeInfoId" class="control-label"></label>
                    <input asp-for="EmployeeInfoId" class="form-control" />
                    <span asp-validation-for="EmployeeInfoId" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label asp-for="PolicyYear" class="control-label"></label>
                    <input asp-for="PolicyYear" class="form-control" />
                    <span asp-validation-for="PolicyYear" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label asp-for="DateFormFilled" class="control-label"></label>
                    <input asp-for="DateFormFilled" class="form-control" />
                    <span asp-validation-for="DateFormFilled" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label asp-for="EmployeeNumber" class="control-label"></label>
                    <input asp-for="EmployeeNumber" class="form-control" />
                    <span asp-validation-for="EmployeeNumber" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label asp-for="LastName" class="control-label"></label>
                    <input asp-for="LastName" class="form-control" />
                    <span asp-validation-for="LastName" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label asp-for="FirstName" class="control-label"></label>
                    <input asp-for="FirstName" class="form-control" />
                    <span asp-validation-for="FirstName" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label asp-for="MiddleName" class="control-label"></label>
                    <input asp-for="MiddleName" class="form-control" />
                    <span asp-validation-for="MiddleName" class="text-danger"></span>
                </div>
                @for (var i = 0; i< Model.EmergencyInfos.Count; i++)
                {
                    <hr />
                    <span>Emergency @i</span>
                    <div class="form-group">
                        <label asp-for="@Model.EmergencyInfos.ToList()[i].EmailAddress" class="control-label"></label>
                        <input asp-for="@Model.EmergencyInfos.ToList()[i].EmailAddress" name="EmergencyInfos[@i].EmailAddress" class="form-control" />
                        <span asp-validation-for="@Model.EmergencyInfos.ToList()[i].EmailAddress" class="text-danger"></span>
                    </div>
                }
                <div class="form-group">
                    <input type="submit" value="Save" class="btn btn-primary" />
                </div>
            </form>
        </div>
    </div>
    

    Then, in the controller: [Note] The Bind attribute can be applied to a class or a method parameter. Specifies which properties of a model should be included in model binding. Since you want to send the complex model and all properties to the post method, there is no need to add the Bind attribute. More detail information, see Model Binding in ASP.NET Core.

            public IActionResult Edit()
            {
                var item = new EmployeeInfo()
                {
                    EmployeeInfoId= 1,
                    FirstName ="Fname",
                    LastName ="Lname",
                    MiddleName="Mname",
                    PolicyYear=10,
                    EmployeeNumber= "n1001",
                    DateFormFilled =DateTime.Now,
                    EmergencyInfos = new List<EmergencyInfo>()
                    {
                        new EmergencyInfo()
                        {
                             EmailAddress="******@hotmail.com"
                        },
                        new EmergencyInfo()
                        {
                             EmailAddress="******@hotmail.com"
                        }
                    }
                };
                return View(item);
            }
            [HttpPost]
            public IActionResult Edit(int id, EmployeeInfo employeeInfo)
            {
                if (ModelState.IsValid)
                {
                    return RedirectToAction(nameof(Index));
                }
                return View();
            }
    

    The result as below:

    image1


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    Best regards,

    Dillion

    1 person found this answer helpful.

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.