Multiple forms on a single MVC page - c#

Below is a screenshot of my page. It has 3 tabs - Details, Users and Rights. Each tab has its own submit button which I need to fire different code within the controller (of which there is no code as of yet).
My question is, how to I have 3 separate forms on a single MVC page and how do I get each Submit button to run the respective code?
View
<div class="row-fluid">
<div class="span12">
<!-- BEGIN INLINE TABS PORTLET-->
<div class="widget">
<div class="widget-title">
<h4><i class="icon-user"></i></h4>
</div>
<div class="widget-body">
<div class="row-fluid">
<div class="span8">
<!--BEGIN TABS-->
<div class="tabbable custom-tab">
<ul class="nav nav-tabs">
<li class="active">Role Details</li>
<li>Users</li>
<li>Rights</li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="tab_1_1">
#using (Html.BeginForm("Details", "RoleController", FormMethod.Get, new { }))
{
#Html.ValidationSummary(true)
<div class="row-fluid">
<div class="span3">
#Html.HiddenFor(model => model.Id)
<div class="control-group">
<label class="control-label">#Html.DisplayNameFor(model => model.RoleName)</label>
<div class="controls controls-row">
#Html.EditorFor(model => model.RoleName)
#Html.ValidationMessageFor(model => model.RoleName)
</div>
</div>
<div class="control-group">
<label class="control-label">#Html.DisplayNameFor(model => model.Description)</label>
<div class="controls controls-row">
#Html.TextArea("Description", Model.Description, new { #cols = 400, #rows = 10 })
</div>
</div>
</div>
</div>
<input type="submit" class="btn btn-success" value="Save" />
}
</div>
<div class="tab-pane" id="tab_1_2">
#using (Html.BeginForm("UsersForRole", "RoleController", FormMethod.Post, new { }))
{
<!-- BEGIN DUAL SELECT-->
<div>
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKMTk5MjI0ODUwOWRkJySmk0TGHOhSY+d9BU9NHeCKW6o=" />
</div>
<div>
<table style="width: 100%;" class="">
<tr>
<td style="width: 35%">
<div class="d-sel-filter">
<span>Filter:</span>
<input type="text" id="box1Filter" />
<button type="button" class="btn" id="box1Clear">X</button>
</div>
<select id="box1View" multiple="multiple" style="height: 300px; width: 75%" runat="server">
</select><br />
<span id="box1Counter" class="countLabel"></span>
<select id="box1Storage">
</select>
</td>
<td style="width: 21%; vertical-align: middle">
<button id="to2" class="btn" type="button"> > </button>
<button id="allTo2" class="btn" type="button"> >> </button>
<button id="allTo1" class="btn" type="button"> << </button>
<button id="to1" class="btn" type="button"> < </button>
</td>
<td style="width: 35%">
<div class="d-sel-filter">
<span>Filter:</span>
<input type="text" id="box2Filter" />
<button type="button" class="btn" id="box2Clear">X</button>
</div>
<select id="box2View" multiple="multiple" style="height: 300px; width: 75%;">
#foreach (var user in Model.Users)
{
<option>#Html.DisplayFor(model => user.SurnameFirstName)</option>
}
</select><br />
<span id="box2Counter" class="countLabel"></span>
<select id="box2Storage">
</select>
</td>
</tr>
</table>
</div>
<div class="mtop20">
<input type="submit" value="Submit" class="btn" />
</div>
<!-- END DUAL SELECT-->
}
</div>
<div class="tab-pane" id="tab_1_3">
#using (Html.BeginForm("RightsForRole", "RoleController", FormMethod.Post, new { }))
{
<table class="table table-striped">
<thead>
<tr>
<th>Right Name</th>
<th>Description</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var right in Model.Rights)
{
<tr>
<td>#Html.DisplayFor(model => right.RightName)</td>
<td>#Html.DisplayFor(model => right.Description)</td>
<td>
<div class="success-toggle-button">
#Html.CheckBoxFor(model => right.Assigned, new { #class = "toggle" })
</div>
</td>
</tr>
}
</tbody>
</table>
}
</div>
</div>
</div>
<!--END TABS-->
</div>
<div class="span4">
<div class="control-group">
<label class="control-label">#Html.DisplayNameFor(model => model.DateCreated)</label>
<div class="controls controls-row">
#Html.EditorFor(model => model.DateCreated, new { #readonly = "readonly" })
</div>
</div>
<div class="control-group">
<label class="control-label">#Html.DisplayNameFor(model => model.CreatedBy)</label>
<div class="controls controls-row">
#Html.EditorFor(model => model.CreatedBy, new { #readonly = "readonly" })
</div>
</div>
<div class="control-group">
<label class="control-label">#Html.DisplayNameFor(model => model.LastUpdated)</label>
<div class="controls controls-row">
#Html.EditorFor(model => model.LastUpdated)
</div>
</div>
<div class="control-group">
<label class="control-label">#Html.DisplayNameFor(model => model.LastUpdateBy)</label>
<div class="controls controls-row">
#Html.EditorFor(model => model.LastUpdateBy)
</div>
</div>
</div>
</div>
</div>
</div>
</div>
UsersForRole controller
[HttpPost]
public ActionResult UsersForRole(RoleModel model)
{
if (ModelState.IsValid)
{
}
return View(model);
}

I think that you may have something wrong in this line:
#using (Html.BeginForm("UsersForRole", "RoleController", FormMethod.Post, new { }))
Controler name in the Html.BeginForm shoudl be only Role unless your controller name is`RoleControllerController?

What you are doing looks fine, you just need to add the other Actions in your controller...
Details
RightsForRole

I think you should use Partial Views.

You can achieved the multiple form inside one form by only using three different Pages(Actions) and use tab as Actionlink. On the Actionlink you call the respective Action.
In your case there will be problem when you will post the form.
Otherwise you should use JQuery to achieve this situation.

Related

Add object to model list from a form ASP.NET Core Razor View

I hope some can help me with this.
I have a list within a model and I want to add objects to that list using a form in a razor view before I save it to a database
This is the model that I have:
public class ActivityForm
{
public string Name { get; set; }
public string Description { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public int Points { get; set; }
public List<Award> Awards { get; set; }
}
This is the code for my view:
#model ActivityForm
#{
ViewData["Title"] = "Activity Details";
}
<section class="my-sm-5">
<div class="container">
<div class="section-header d-flex mb-5">
<h1 class="h-02 flex-grow-1">Activity Details</h1>
</div>
<div class="row">
<div class="col-md-7">
<div class="section-header d-flex mb-5">
<h1 class="h-04 flex-grow-1">Form</h1>
</div>
<form id="form" class="row g-3 w-90" asp-action="Create">
<div class="col-md-12">
<label asp-for="Name" class="form-label">#Html.DisplayNameFor(model => model.Name)</label>
<input asp-for="Name" type="text" class="form-control" id="inputEmail4"
placeholder="#Html.DisplayNameFor(model => model.Name)">
<span asp-validation-for="Name" class="invalid-feedback"></span>
</div>
<div class="col-12">
<label asp-for="Description" class="form-label">#Html.DisplayNameFor(model =>
model.Description)</label>
<textarea asp-for="Description" class="form-control" id="exampleFormControlTextarea1" rows="5"
placeholder="#Html.DisplayNameFor(model => model.Description)"></textarea>
<span asp-validation-for="Description" class="invalid-feedback"></span>
</div>
<div class="col-md-4">
<label asp-for="StartDate" class="form-label">#Html.DisplayNameFor(model =>
model.StartDate)</label>
<input asp-for="StartDate" type="date" class="form-control"
placeholder="#Html.DisplayNameFor(model => model.StartDate)">
<span asp-validation-for="StartDate" class="invalid-feedback"></span>
</div>
<div class="col-md-4">
<label asp-for="EndDate" class="form-label">#Html.DisplayNameFor(model => model.EndDate)</label>
<input asp-for="EndDate" type="date" class="form-control"
placeholder="#Html.DisplayNameFor(model => model.EndDate)">
<span asp-validation-for="EndDate" class="invalid-feedback"></span>
</div>
<div class="col-md-4 mb-6">
<label asp-for="Points" class="form-label">#Html.DisplayNameFor(model => model.Points)</label>
<input asp-for="Points" type="number" class="form-control"
placeholder="#Html.DisplayNameFor(model => model.Points)">
<span asp-validation-for="Points" class="invalid-feedback"></span>
</div>
<div class="col-8 d-grid gap-2">
<a class="btn btn-primary mb-2" data-bs-toggle="modal" data-bs-target="#add-award">Add award</a>
<div class="row">
<div class="col-md-6">
<a class="btn btn-outline-primary w-100" data-bs-toggle="modal"
data-bs-target="#cancel-activity">Cancel</a>
</div>
<div class="col-md-6">
<a class="btn btn-outline-primary w-100" data-bs-toggle="modal"
data-bs-target="#post-activity">Post Activity</a>
</div>
</div>
</div>
</form>
</div>
<div class="col-md-5">
<div class="section-header d-flex mb-5">
<h1 class="h-04 flex-grow-1">Awards</h1>
</div>
<table class="table">
<thead>
<tr>
<th scope="col">Award name</th>
<th scope="col">Description</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
#for (int i = 0; i < 1; i++)
{
<tr>
<td>Award Name</td>
<td>Award Description</td>
<td>
<a class="btn btn-outline-primary btn-sm">Edit</a>
<a class="btn btn-outline-primary btn-sm">Remove</a>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
</div>
</section>
<div class="modal" id="add-award" tabindex="-1">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content br-20 pd-20">
<div class="modal-header justify-content-center">
<h5 class="modal-title h-04 text-prim-color">Award details</h5>
</div>
<form class="row g-3">
<div class="modal-body">
<div class="row g-3">
<div class="col-md-12">
<label asp-for="Award.Name" class="form-label">Name</label>
<input asp-for="Award.Name" type="text" class="form-control" id="inputEmail4">
</div>
<div class="col-12">
<label asp-for="Award.Description" for="inputAddress" class="form-label">Description</label>
<textarea asp-for="Award.Description" class="form-control" id="exampleFormControlTextarea1" rows="5"></textarea>
</div>
</div>
</div>
<div class="modal-footer justify-content-center">
<button type="button" class="btn btn-outline-primary w-100" data-bs-dismiss="modal">Close</button>
<input class="btn btn-primary w-100" type="submit" value="Confirm"></input>
</div>
</form>
</div>
</div>
</div>
My form is within a modal and when I click the submit button I want to create an Award object with the values from the form. After the object is created I want to add it to the Awards List and have the changes reflect on the view.
This is what the View looks like:
View with modal
And this is how it will look like after the object has been added:
View after object is added
You should first fix some issues:
Right now your form does not have a binding for the ActivityForm.Awards property. You should change:
<tbody>
#for (int i = 0; i < 1; i++)
{
<tr>
<td>Award Name</td>
<td>Award Description</td>
<td>
<a class="btn btn-outline-primary btn-sm">Edit</a>
<a class="btn btn-outline-primary btn-sm">Remove</a>
</td>
</tr>
}
</tbody>
To:
<tbody>
#for (var i = 0; i < Model.Awards.Count; i++)
{
<input type="hidden" asp-for="#Model.Awards[i].Name" />
<input type="hidden" asp-for="#Model.Awards[i].Description" />
<tr>
<td>#Model.Awards[i].Name</td>
<td>#Model.Awards[i].Description</td>
<td>
<a class="btn btn-outline-primary btn-sm">Edit</a>
<a class="btn btn-outline-primary btn-sm">Remove</a>
</td>
</tr>
}
</tbody>
Documentation for binding model to a collection: https://learn.microsoft.com/en-us/aspnet/core/mvc/models/model-binding?view=aspnetcore-6.0#collections-1
Your form should wrap around both Form and Awards sections:
<form id="form" class="row g-3 w-90" asp-action="Create">
<div class="col-md-7">
<div class="section-header d-flex mb-5">
<h1 class="h-04 flex-grow-1">Form</h1>
</div>
...
</div>
<div class="col-md-5">
<div class="section-header d-flex mb-5">
<h1 class="h-04 flex-grow-1">Awards</h1>
</div>
...
</div>
</form>
You should also change:
<a class="btn btn-outline-primary w-100" data-bs-toggle="modal" data-bs-target="#post-activity">Post Activity</a>
to an actual submit button:
<button type="submit" class="btn btn-outline-primary w-100">Post Activity</button>
Now if you manually add some awards to the Awards list from your Controller,
return View(new ActivityForm
{
Awards = new List<Award>
{
new Award { Name = "Name", Description = "Descr" },
new Award { Name = "Award 2", Description = "Descr 2" }
}
});
the awards will be displayed properly and also when you submit the form the ActivityForm.Awards list will be populated with the awards you added manually.
These issues need to be fixed before you go on and implement the add award form inside the modal.

Model List returning as null from view to controller ASP.NET Core MVC

I'm having trouble with a list within my model returning as null even tho in the view it clearly has some value.
I had trouble trying to add objects to my model's list, someone helped me and my problem was half solved. This is the code I came up with after the help
My view:
#model ActivityForm
#{
ViewData["Title"] = "Activity Details";
}
<section class="my-sm-5">
<div class="container">
<div class="section-header d-flex mb-5">
<h1 class="h-02 flex-grow-1">Activity Details</h1>
</div>
<div class="row">
<div class="col-md-7">
<div class="section-header d-flex mb-5">
<h1 class="h-04 flex-grow-1">Form</h1>
</div>
<form id="form" class="row g-3 w-90" asp-action="Create">
<div class="col-md-12">
<label asp-for="Name" class="form-label">#Html.DisplayNameFor(model => model.Name)</label>
<input asp-for="Name" type="text" class="form-control" id="inputEmail4"
placeholder="#Html.DisplayNameFor(model => model.Name)">
<span asp-validation-for="Name" class="invalid-feedback"></span>
</div>
<div class="col-12">
<label asp-for="Description" class="form-label">#Html.DisplayNameFor(model =>
model.Description)</label>
<textarea asp-for="Description" class="form-control" id="exampleFormControlTextarea1" rows="5"
placeholder="#Html.DisplayNameFor(model => model.Description)"></textarea>
<span asp-validation-for="Description" class="invalid-feedback"></span>
</div>
<div class="col-md-4">
<label asp-for="StartDate" class="form-label">#Html.DisplayNameFor(model =>
model.StartDate)</label>
<input asp-for="StartDate" type="date" class="form-control"
placeholder="#Html.DisplayNameFor(model => model.StartDate)">
<span asp-validation-for="StartDate" class="invalid-feedback"></span>
</div>
<div class="col-md-4">
<label asp-for="EndDate" class="form-label">#Html.DisplayNameFor(model => model.EndDate)</label>
<input asp-for="EndDate" type="date" class="form-control"
placeholder="#Html.DisplayNameFor(model => model.EndDate)">
<span asp-validation-for="EndDate" class="invalid-feedback"></span>
</div>
<div class="col-md-4 mb-6">
<label asp-for="Points" class="form-label">#Html.DisplayNameFor(model => model.Points)</label>
<input asp-for="Points" type="number" class="form-control"
placeholder="#Html.DisplayNameFor(model => model.Points)">
<span asp-validation-for="Points" class="invalid-feedback"></span>
</div>
<div class="col-8 d-grid gap-2">
<a class="btn btn-primary mb-2" data-bs-toggle="modal" data-bs-target="#add-award">Add award</a>
<div class="row">
<div class="col-md-6">
<a class="btn btn-outline-primary w-100" data-bs-toggle="modal"
data-bs-target="#cancel-activity">Cancel</a>
</div>
<div class="col-md-6">
<a class="btn btn-outline-primary w-100" data-bs-toggle="modal"
data-bs-target="#post-activity">Post Activity</a>
</div>
</div>
</div>
<div class="modal" id="add-award" tabindex="-1">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content br-20 pd-20">
<div class="modal-header justify-content-center">
<h5 class="modal-title h-04 text-prim-color">Award details</h5>
</div>
<div class="row g-3">
<div class="modal-body">
<div class="row g-3">
<div class="col-md-12">
<label asp-for="Award.Name" class="form-label">Name</label>
<input asp-for="Award.Name" type="text" class="form-control"
id="award-name">
</div>
<div class="col-12">
<label asp-for="Award.Description" for="inputAddress"
class="form-label">Description</label>
<textarea asp-for="Award.Description" class="form-control"
id="award-description" rows="5"></textarea>
</div>
</div>
</div>
<div class="modal-footer justify-content-center">
<button type="button" class="btn btn-outline-primary w-100"
data-bs-dismiss="modal">Close</button>
<input class="btn btn-primary w-100" type="submit" value="Confirm"></input>
</div>
</div>
</div>
</div>
</div>
</form>
</div>
<div class="col-md-5">
<div class="section-header d-flex mb-5">
<h1 class="h-04 flex-grow-1">Awards</h1>
</div>
<table class="table">
<thead>
<tr>
<th scope="col">Award name</th>
<th scope="col">Description</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
#if (Model.Awards != null)
{
foreach (var item in Model.Awards)
{
<tr>
<td>#item.Name</td>
<td>#item.Description</td>
<td>
<a class="btn btn-outline-primary btn-sm">Edit</a>
<a class="btn btn-outline-primary btn-sm">Remove</a>
</td>
</tr>
}
}
</tbody>
</table>
</div>
</div>
</div>
</section>
Method in controller:
[HttpPost]
public async Task<IActionResult> Create(ActivityForm data)
{
var award = data.Award;
if (award.Name != null && award.Description != null)
{
if (data.Awards == null) data.Awards = new List<AwardForm>();
data.Awards.Add(new AwardForm { Name = award.Name, Description = award.Description });
data.Award.Name = "";
data.Award.Description = "";
return View(data);
}
if (!ModelState.IsValid)
{
return View(data);
}
string userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
await service.NewActivityAsync(data, userId);
return RedirectToAction(nameof(Index));
}
Model
public class ActivityForm
{
public string Name { get; set; }
public string Description { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public int Points { get; set; }
public AwardForm Award { get; set; }
public List<AwardForm> Awards { get; set; }
}
Everything was now working as intended but I had one more issue left. When I try to add another Award to the list, the list is returned to the controller method as null.
I'm not really sure if the issue is related to binding, I have noticed that every other value is bound and is returning the expected value except the list which is not bound.
Change the foreach loop to:
<tbody>
#if (Model.Awards != null)
{
#for (var i = 0; i < Model.Awards.Count; i++)
{
<input type="hidden" asp-for="#Model.Awards[i].Name" />
<input type="hidden" asp-for="#Model.Awards[i].Description" />
<tr>
<td>#Model.Awards[i].Name</td>
<td>#Model.Awards[i].Description</td>
<td>
<a class="btn btn-outline-primary btn-sm">Edit</a>
<a class="btn btn-outline-primary btn-sm">Remove</a>
</td>
</tr>
}
}
</tbody>
This has same effect to what #Victor suggested but using input tag helper instead of html helper.
Documentation for binding model to a collection: https://learn.microsoft.com/en-us/aspnet/core/mvc/models/model-binding?view=aspnetcore-6.0#collections-1
Also your form should wrap around both Form and Awards sections:
<form id="form" class="row g-3 w-90" asp-action="Create">
<div class="col-md-7">
<div class="section-header d-flex mb-5">
<h1 class="h-04 flex-grow-1">Form</h1>
</div>
...
</div>
<div class="col-md-5">
<div class="section-header d-flex mb-5">
<h1 class="h-04 flex-grow-1">Awards</h1>
</div>
...
</div>
</form>
The list binding context should include indexes to work properly.
Add to following code located below right after declaration of the <form> tag:
<form id="form" class="row g-3 w-90" asp-action="Create">
#if (Model.Awards != null)
{
for (int i=0; i < Model.Awards.Count; i++)
{
#Html.Hidden("Awards[" + i + "].Name", Model.Awards[i].Name)
#Html.Hidden("Awards[" + i + "].Description", Model.Awards[i].Description)
}
}
... your markup and control that performs the submit are located here
</form>
To be a part of the binding context these hidden fields should be declared inside the <form> from that the submit is performing.

FindAsync(id); doesn't update on screen, only when I refresh the URL

I started to learn some basic c# and im trying to find my way into ASP.net
I am running the following code with some help from this video: https://www.youtube.com/watch?v=C5cnZ-gZy2I (time stamp: 1 hour and 50min)
public class BestellenModel : PageModel
{
private ApplicationDbContext _db;
public BestellenModel(ApplicationDbContext db)
{
_db = db;
}
[BindProperty]
public Bedrijven Bedrijven { get; set; }
public async Task OnGet(int id)
{
Bedrijven = await _db.Bedrijven.FindAsync(id);
}
}
}
In the video whenever the edit button is pressed the right data from the data base appears on screen. For me nothing appears but whenever i click on my url and hit enter again the data appears.
I tried the debug option within VS and i saw that the line FindAsync doesn't run when hitting the button. But when i click enter on the url then it runs the code. My url looks like this: https://localhost:7005/Bedrijfslijst/Bestellen?id=32
Can anyone tell me what i am missing here? because i am a bit stuck.
Edit:
Now whenever the client Clicks on the "kopen" button it needs to render the data from the db to the fields.
This is a screenshot from the yt video, its supposed to show the data when the page is loaded. For me its not loading but whenever i click on the url and hit enter then the db data will load in.
cshtml script:
#page
#model test1v1.Pages.Bedrijfslijst.BestellenModel
<br />
<h2 class="text-primary">Rapport bestellen</h2>
<br />
<div class="border container" style="padding:120px;">
<form method="post">
<div class="text-danger" asp-validation-summary="ModelOnly"></div>
<div class="form-group row" style="padding:10px;">
<div class="col-4">
<label asp-for="Bedrijven.Kvk"></label>
</div>
<div class="col-4">
<input asp-for="Bedrijven.Kvk" class="form-control" />
</div>
<span asp-validation-for="Bedrijven.Kvk" class="text-danger"></span>
</div>
<div class="form-group row" style="padding:10px;">
<div class="col-4">
<label asp-for="Bedrijven.Bedrijfsnaam"></label>
</div>
<div class="col-4">
<input asp-for="Bedrijven.Bedrijfsnaam" class="form-control" />
</div>
<span asp-validation-for="Bedrijven.Bedrijfsnaam" class="text-danger"></span>
</div>
<div class="form-group row" style="padding:10px;">
<div class="col-4">
<label asp-for="Bedrijven.Adres"></label>
</div>
<div class="col-4">
<input asp-for="Bedrijven.Adres" class="form-control" />
</div>
<span asp-validation-for="Bedrijven.Adres" class="text-danger"></span>
</div>
<div class="form-group row" style="padding:10px;">
<div class="col-3 offset-4">
<input type ="submit" value="Bestellen" class="btn btn-success form-control" />
</div>
<div class="col-3">
<a asp-page="index" class="btn btn-primary form-control">Terug</a>
</div>
</div>
</form>
</div>
#section Scripts{
<partial name ="_ValidationScriptsPartial"/>
}
Edit2:
#page
#model test1v1.Pages.Bedrijfslijst.IndexModel
<br />
<div class="container row p-0 m-0">
<div class="col-9">
<h2 class="text-primary">Bedrijf Lijst</h2>
</div>
<div class="col-3">
<a asp-page="Zoeken" class="btn btn-primary form-control text-white">Bedrijf Zoeken</a>
</div>
<div class= "col-10 border p-4 mt-4">
<form method="post">
#if (Model.Bedrijven.Count() > 0)
{
<table class="table table-striped border">
<tr class="table-secondary">
<th>
<label asp-for="Bedrijven.FirstOrDefault().Kvk"></label>
</th>
<th>
#*#Html.DisplayNameFor(m=>m.Books.FirstOrDefault().Author)*#
<label asp-for="Bedrijven.FirstOrDefault().Bedrijfsnaam"></label>
</th>
<th>
<label asp-for="Bedrijven.FirstOrDefault().Adres"></label>
</th>
<th>
</th>
</tr>
#foreach (var item in Model.Bedrijven)
{
<tr>
<td>
#Html.DisplayFor(m=>item.Bedrijfsnaam)
</td>
<td>
#Html.DisplayFor(m=>item.Kvk)
</td>
<td>
#Html.DisplayFor(m=>item.Adres)
</td>
<td>
<button asp-page="Bestellen" asp-route-id="#item.Id" class="btn btn-primary btn-sm">Kopen</button>
</td>
</tr>
}
</table>
}
else
{
<p>Geen Bedrijven Gevonden.</p>
}
</form>
</div>
</div>

C# Razor pages Partial View Model is null on submit

I am new to Razor pages and trying to create a page with a partial view. The partial view has a dropdownlist and a text input for Quantity field and a submit button. The Partial View renders correctly but when I click on the Submit button the Model passed to the Code behind has no value.
Here is the code I have
_PartialAddons.cshtml
#*
For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
*#
#{
}
#model Public.Areas.Register.AddonListDto
<form method="post">
#Html.HiddenFor(Model => Model.Quantity)
<div style="padding:5px;">
<b>NZD $45</b>
</div>
<div>
<div style="padding:5px;">
<select id="skuSelect" asp-for="SelectedSkus" asp-items="#(new SelectList(Model.AddonSkus,"SkuId","SkuName"))" class="form-control">
<option>Please select one</option>
</select>
</div>
<div style="padding:5px;">
<input type="hidden" name="handler" value="Quantity" />
<input asp-for="Quantity" name="Quantity" class="form-control ng-untouched ng-pristine ng-valid" max="999" min="0" style="width:150px;" type="number" value="0" id="#Model.Id">
</div>
</div>
<div style="padding:5px;">
<a class="btn green" asp-page-handler="AddToCart">Add to Cart</a>
</div>
</form>
This is the Main Page
#foreach (var addons in Model.StoreAddonList)
{
<div class="panel card panel-default" style="margin-top:10px;">
<div class="panel-heading card-header" role="tab">
<div class="panel-title">
<div class="accordion-toggle" role="button" aria-expanded="true">
<div accordion-heading="" style="width:100%;">
#addons.Title
<i class="pull-right float-xs-right glyphicon glyphicon-chevron-down"></i>
</div>
</div>
</div>
</div>
<div class="panel-collapse collapse in show" role="tabpanel" style="overflow: visible; height: auto; display: block;" aria-expanded="true" aria-hidden="false">
<div class="panel-body card-block card-body">
<div style="padding-top:10px;background-color:#ffffff;clear:both;">
<div style="width:100%">
<div style="float:left;width:20%;text-align:left;">
Name
</div>
<div style="float:left;width:30%;padding-left:10px;">
#addons.Description
</div>
</div>
<div style="float:left;width:40%;padding-left:10px;">
<div>
#{
await Html.RenderPartialAsync("_PartialAddons.cshtml", addons);
}
</div>
</div>
<div style="clear:both;">
</div>
</div>
</div>
</div>
</div>
}
This is the Index.cshtml.cs to handle the submit
public ActionResult OnGetAddToCart(AddonListDto addOnList)
{
var sass = Quantity;
var tass = SelectedSkus;
return null;
}
The AddonListDto is null on the OnGetAddToCart Method. Have been trying to get this working for the past two days. Any help would be greatly appriciated
If you want to submit your data, you need to use OnPost instead of OnGet in razor pages and set the handler name in the <form> tag. For example:
handler:
public ActionResult OnPostAddToCart(AddonListDto addOnList)
partial view:
#model Public.Areas.Register.AddonListDto
<form method="post" asp-page-handler="AddToCart">
#Html.HiddenFor(Model => Model.Quantity)
<div style="padding:5px;">
<b>NZD $45</b>
</div>
<div>
<div style="padding:5px;">
<select id="skuSelect" asp-for="SelectedSkus" asp-items="#(new SelectList(Model.AddonSkus,"SkuId","SkuName"))" class="form-control">
<option>Please select one</option>
</select>
</div>
<div style="padding:5px;">
<input type="hidden" name="handler" value="Quantity" />
<input asp-for="Quantity" name="Quantity" class="form-control ng-untouched ng-pristine ng-valid" max="999" min="0" style="width:150px;" type="number" value="0" id="#Model.Id">
</div>
</div>
<div style="padding:5px;">
<input type="submit" value="Add To Cart" class="btn btn-primary" />
</div>
</form>

Partial view button submit not call httpost, call a action to view

view :
<div id="ReportChange">
#{
ViewDataDictionary vDataDictonary = new ViewDataDictionary();
vDataDictonary.Add(new KeyValuePair<string, object>("ReportType", ViewData["ReportType"]));
vDataDictonary.Add(new KeyValuePair<string,object>("Agencias", ViewData["Agencias"]));
vDataDictonary.Add(new KeyValuePair<string, object>("SendType", ViewData["SendType"]));
vDataDictonary.Add(new KeyValuePair<string, object>("OrderStatus", ViewData["OrderStatus"]));
vDataDictonary.Add(new KeyValuePair<string, object>("User", ViewData["User"]));
vDataDictonary.Add(new KeyValuePair<string, object>("ServicesType", ViewData["ServicesType"]));
if (Model.report == null){
Html.RenderPartial("getReport", new ReportSchedule() { StartDate = DateTime.Now, EndDate=DateTime.Now}, vDataDictonary);
}
else {
Html.RenderPartial("getReport", Model.report, vDataDictonary);
}
}
#if (Model.lReport.Count() == 0)
{
<h4 class="alert alert-danger text-center">Error.</h4>
}
else
{
<div class="container-fluid container-fixed-lg bg-white" id="viewform">
<div class="panel panel-transparent">
<div class="panel-heading">
<div class="panel-title"></div>
<div class="clearfix"></div>
</div>
<div class="panel-body">
<table class="table table-hover demo-table-search" id="tableWithSearch">
<thead>
<tr>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.lReport)
{
<tr>
<td>#Html.DisplayFor(modelItem => item.ReportType.Description)</td>
<td>#(item.EndDate.HasValue ? String.Concat(item.StartDate.ToString("dd/MM/yyyy"), " - ", item.EndDate.Value.ToString("dd/MM/yyyy")) : item.StartDate.ToString("dd/MM/yyyy"))</td>
<td>#item.StartDate - #item.EndTime </td>
<td>#Html.DisplayFor(modelItem=> item.Agency.CorporateName) </td>
<td>#Html.DisplayFor(modelItem=> item.CostCenter.Description)</td>
<td>#Html.DisplayFor(modelItem=> item.User.Name )</td>
<td>#Html.DisplayFor(modelItem=>item.OrderStatus.Description ) </td>
<td>#Html.DisplayFor(modelItem=> item.ServiceType.Description ) </td>
<td>#Html.CheckBox("A", #item.Live.Equals(0) ? false : true, new {disabled="readonly" })</td>
<td class="v-align-middle">
<div class="btn-group">
<input type="button" class="btn btn-info btn-sm" id="#item.ReportScheduleID" onclick="getReport(this.id)" />
#Html.ActionLink(item.Live ? "D" : "A", "Live", new { id = item.CostCenterID }, new { #class ="btn btn-danger btn-sm buttonLive" })
</div>
</td>
</tr>
}
</tbody>
</table>
<div class="row"> </div>
</div>
</div>
</div>
}
My partial view :
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<form id="frm" class="form-horizontal well">
#if (Model.AgencyID.Equals(0))
{
using (Html.BeginForm("getReport", "ReportSchedules"))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
#Html.HiddenFor(_ => _.ReportScheduleID)
<div class="row">
<div class="col-md-12">
<div class="form-group">
<label class="control-label col-md-1">Relatório</label>
#Html.DropDownListFor(m=>m.ReportTypeID,(SelectList) ViewData["ReportType"],"Atendimento por Agência")
#Html.ValidationMessageFor(m=>m.ReportTypeID)
</div>
</div>
<div class="col-md-12">
<div class="form-group">
<label class="control-label col-md-1">Início</label>
<input type="text" id="date" name="date" class="col-md-2 smallDate" value="#Model.StartDate.ToShortDateString()"/>
#Html.ValidationMessageFor(m=>m.StartDate)
#Html.TextBoxFor(m=>m.StartTime,new {#class="col-md-1 smallDateMargin"})
#Html.ValidationMessageFor(m => m.StartTime)
</div>
</div>
<div class="col-md-12">
<div class="form-group">
<label class="control-label col-md-1">Periodicidade</label>
#Html.DropDownListFor(m=>m.SendTypeID,(SelectList) ViewData["SendType"],"Selecione")
#Html.ValidationMessageFor(m=>m.SendTypeID)
</div>
</div>
<div class="col-md-10">
<h6>Configurações avançadas<a data-toggle="tooltip" class="tooltipLink" data-original-title="Data até quando o relatório será enviado.">
<span class="glyphicon glyphicon-question-sign"></span>
</a></h6>
<div class="form-group" style="border: 1px dashed #ccc;">
<div class="form-group">
<label class="control-label col-md-1">
<input type="checkbox" name="dateEndSelected" id="dateEndSelected" value="#Model.Live"/> Fim</label>
<input type="text" id="dataFinalSelected" name="dataFinalSelected" style="display:none;" value="false"/>
<input type="text" id="dateFinal" name="dateFinal" style="display:none;"class="col-md-2 smallDate" value="#Model.EndDate.Value.ToShortDateString()"/>
#Html.TextBoxFor(m=>m.EndTime,new {#class="col-md-1 smallDateMargin"})
#Html.ValidationMessageFor(m=>m.EndTime)
</div>
</div>
</div>
<div class="col-md-10">
<h6>Filtrar por:</h6>
<div class="form-group" style="border: 1px dashed #ccc;">
<div class="col-md-10">
#Html.DropDownListFor(m=>m.AgencyID, (SelectList) ViewData["Agencias"],"Agências",new {#class="col-md-1",id="agencia",name="agencia"})
#Html.ValidationMessageFor(m => m.AgencyID)
#Html.DropDownListFor(m=>m.OrderStatusID, (SelectList) ViewData["OrderStatus"],"Status",new {#class="col-md-2"})
#Html.ValidationMessageFor(m=>m.OrderStatusID)
#Html.DropDownListFor(m=>m.UserID, (SelectList) ViewData["User"],"Usuários",new {#class="col-md-3"})
#Html.ValidationMessageFor(m=>m.UserID)
</div>
<div class="col-md-10">
#Html.DropDownList("dpdCostCenter", new List<SelectListItem>(), "Selecione", new { #class = "col-md-1" })
#Html.DropDownListFor(m=>m.ServiceTypeID,(SelectList) ViewData["ServicesType"],"Tipos de atendimento",new {#class="col-md-2"})
#Html.ValidationMessageFor(m=>m.ServiceTypeID)
</div>
</div>
</div>
<div class="col-md-10">
<div class="form-group">
<div class="input-group pull-right marginTopBot-sm input-group-sm" style="padding-left: 5px;">
<input type="submit" value="Agendar o envio" class="btn btn-success" onclick="$('#getResponse').submit()" />
</div>
</div>
</div>
</div>
}
}
else
But if i click in button submit it goes to the index action of view
public ActionResult Index()
And not to :
[HTTPPOST]
public ActionResult getReport(ReportSchedule model)
{
if (ModelState.IsValid)
{
db.ReportSchedule.Add(model);
db.SaveChanges();
}
else
{
return PartialView(model);
}
return RedirectToAction("Index");
}
But i need submit button call getReport to validate a model and save in db
You have nested forms which are invalid html and not supported. Remove the outer form tag from the partial (including the AntiForgeryToken and ValidationSummary above it
<form id="frm" class="form-horizontal well"> // remove this and its corresponding closing tag

Categories

Resources