简体   繁体   中英

Passing Model's Properties as parameters to View Controller

I am an intern on .NET, and I am still at the learning part. I came to a crossroads regarding an issue about ViewComponent and Model properties

I have the following Model

namespace MVCHotel.Models
{
   public class Guest
   {
    public int ID { get; set; }

    [DisplayName("First Name")]
    [Required(ErrorMessage = "First name required")]
    public string FirstName { get; set; }

    [DisplayName("Last Name")]
    [Required(ErrorMessage = "Last name required")]
    public string LastName { get; set; }

    [DisplayName("Arrival Date")]
    [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
    [DataType(DataType.Date)]
    public DateTime ArrivalDate { get; set; }

    [DisplayName("Departure Date")]
    [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
    [DataType(DataType.Date)]
    public DateTime DepartureDate { get; set; }
   }
}

and the following View containing a ViewComponent ReservationsList which displays the data on rows (First Name, Last Name, Arrival Date, Departure Date)

@model IEnumerable<MVCHotel.Models.Guest>

@{
    ViewData["Title"] = "Reservations";
}

<h2>@ViewData["Title"]</h2>

<div class="btn btn-default">
    <a asp-action="Create">Create new reservation</a>
</div>

<br />
<br />

<form asp-controller="Guests" asp-action="Reservations">
    <div>
        First Name: <input type="text" name="firstName" required>
        Last Name: <input type="text" name="lastName" required>
        <input id="submit" type="submit" value="Search" />
    </div>
</form>

<hr />

<div>
    @await Component.InvokeAsync("ReservationsList")
</div>

What I am trying to do is to pass the firstName and lastName properties (which I set in the input from the form ((I have two inputs and a button which filters my data based on the input))) to the ViewComponent but it seems that @model.FirstName or @model.LastName inside the Component.InvokeAsync method doesn't work.

Do you have any ideas how can I do this or what approach should I look for? Thank you very much for your time!

PS Yes, I can do it through ViewData inside the Controller but my mentor said that there's a better way by passing the parameters from model but I didn't found any specific answers about it.

EDIT WITH SOLUTION

Eventually this is the solution implemented in the View. I used the JQuery Unobtrusive AJAX library with data-ajax helpers for modifying the form.

<form asp-controller="Guests" asp-action="SearchReservations" data-ajax="true" data-ajax-method="POST" data-ajax-update="#reservationsList" data-ajax-mode="replace" data-ajax-success="resultEmpty()">
    <div>
        First Name: <input type="text" name="firstName" required>
        Last Name: <input type="text" name="lastName" required>
        <input id="submit" type="submit" value="Search" />
    </div>
</form>

The other thing that required changes was the ViewComponent class where I had to pass the Guest model object as parameter (I was passing First and Last name previously).

namespace MVCHotel.ViewComponents
{
    [ViewComponent(Name = "ReservationsList")]
    public class ReservationsListViewComponent : ViewComponent
    {
        private readonly MVCHotelContext _context;

        public ReservationsListViewComponent(MVCHotelContext context)
        {
            _context = context;
        }

        private Task<List<Guest>> GetReservationsAsync(Guest guest)
        {
            var reservations = from r in _context.Guest
                               select r;

            if (!String.IsNullOrEmpty(guest.FirstName) && !String.IsNullOrEmpty(guest.LastName))
            {
                reservations = reservations.Where(x => x.FirstName.Contains(guest.FirstName) && x.LastName.Contains(guest.LastName));
            }

            return reservations.ToListAsync();
        }

        public async Task<IViewComponentResult> InvokeAsync(Guest guest)
        {
            var items = await GetReservationsAsync(guest);
            return View(items);
        }
    }
}

I hope this will help other people too, in the future.

Component.InvokeAsync can be passed an anonymous object which will end up as params on your view component's InvokeAsync method. In other words:

@await Component.InvokeAsync("ReservationList", new { ... params here ... })

However, what you're attempting to do here is not actually possible. Your model, view component, etc. all exist server-side and everything is processed before the response is sent to the client. The client (web browser in this case) receives the response and renders all the HTML and displays it to the user. It's only at that point that the user enters something into your form fields. The server is not involved at all here at this stage, meaning you cannot pass anything to your view component. If you need to involve the server again, you have to use AJAX to submit a new request to the server, potentially doing something like posting the user input for these form fields and having the server return a partial HTML document. You can then, via JavaScript, replace some element in your DOM with that new HTML.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM