How to add a value to a class if the class contains LIST<class> - asp.net

I have a class graf.
public class Graf
{
public List<Point> first { get; set; }
public List<Point> second { get; set; }
}
This class contains List
public class Point
{
public int x { get; set; }
public int y { get; set; }
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
}
I need to add a Point into class Graf from index.cshtml:
#model WebApplication2.Models.Graf
<table>
<tr>
<td></td>
<td>
<div class="item">
<label>Y</label>
<input name="Y11" value="#Model.first" /> --------??
</div>
</td>
</tr>
</table>
<input type="submit" value="Send" />
But i dont now how i can input into Graf class Point?
How can I do it?

Ok. So let's start from a client-side code.I suppose that you have a next Index.cshtml view.
<!-- You use this code to display data from your model -->
<table>
<tr>
<td></td>
<td>
<div class="item">
<label>Y</label>
<input name="Y11" value="#Model.first" /> --------??
</div>
</td>
</tr>
</table>
Than you need a code that post new Point object from your view to controller.It could be like something like this:
<form asp-controller="Home" asp-action="InsertPoint" method="post">
X value: <input type="text" name="x"><br>
Y value: <input type="text" name="y"><br>
<input type="submit" value="Submit">
</form>
In your controller you should create action with following signature
[HttpPost]
public async Task<IActionResult> InsertPoint(Point point)
{
//Validation and insertion to list
return View();
}
NB
It's not an ideal solution. You could perform this task in many different ways. My aim, is just to show you the basic idea how it could be done. If you need more information you could start from this article
And of course, keep in mind that google is your good friend.

Related

How to Edit Image in Existing Member

I Use bootstrap cards and i want picture can also edit on existing user or i Edit picture of any member
This is my Controller
This is my edit Functionality where i can edit My Member so i want i update all existing user picture
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var member = await _context.Member.FindAsync(id);
if (member == null)
{
return NotFound();
}
return View(member);
}
// POST: HomePage/Edit/5
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("MemberId,Name,Gender,DOB,MaritalStatus,Address,PhoneNo,Skills,Hobbies,JobTitle,Technology")] Member member)
{
if (id != member.MemberId)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(member);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MemberExists(member.MemberId))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(member);
}
This is a View of my project this is same as create class
<div class="row">
<div class="form-group col-md-4">
<label class="col-md-2 control-label">MemberImage</label>
<div class="col-md-10">
<div id="chooseFile">
<input class="form-control" type="file" name="photo" accept="image/*" />
</div>
</div>
</div>
</div>
when i edit the one existing member
2.i add image
and save it will save the img but now they cannot save image
Exception Occurs when i open edit
*Edit Page Code
<div class="row">
<div class="form-group col-md-4">
<label class="col-md-2 control-label">MemberPicture</label>
<div class="col-md-10">
<img src="~/ImageName/Cover/#Model.Member.ImageName"
class="rounded-square"
height="50" width="75"
style="border:1px"
asp-append-version="true" accept="image/*" />
<span>#Model.Member.ImageName</span>
<div id="chooseFile">
<input class="form-control" type="file" name="photo" accept="image/*" />
</div>
</div>
</div>
</div>
View Model
using System;
using TeamManagement.Models;
namespace TeamManagement.ViewModel
{
public class MemberViewModel
{
public Member Member { get; set; }
public IFormFile? Photo { get; set; }
}
}
This is my edit Functionality where I can edit My Member so I want I update all existing user picture?
If you look into the Member List, it usually contains rows of users along with Id. So we have to find the particular Id and then need to retrieve the value of that Id finally we will update the existing value with the new value. As seen on the screenshot below
Algorithm
From The Member List Click On Particular Member Id
Find The Member Information By that Id
Load The Edit Page With That Id Same As Create Member Page
After Required Change Submit the Edit Page Which Containing the Member Model Data With A ID
Save the Image Into Folder First Same As Create
Search The Member Object By Id
Set New Value Into The Member Object You Have Found In Step 6
Save The Context And Redirect To Member List
Controller Action For Loading Edit Page
public async Task<IActionResult> EditMember(int memberId)
{
var memeber = await _context.Members.FindAsync(memberId); // Getting member by Id from database
return View(new MemberViewModel() { Member = memeber });
}
View Model
public class MemberViewModel
{
public Member Member { get; set; }
public IFormFile? Photo { get; set; }
}
View Edit
#model DotNet6MVCWebApp.Models.MemberViewModel
<div>
<form asp-action="EditMember" method="post" enctype="multipart/form-data">
<div asp-validation-summary="ModelOnly"></div><input type="hidden" asp-for="Member.MemberId" />
<div>
<h4><strong>Member Details</strong> </h4>
<table class="table table-sm table-bordered table-striped">
<tr>
<th> <label asp-for="Member.Name"></label></th>
<td> <input asp-for="Member.Name" class="form-control" placeholder="Enter member name" /><span asp-validation-for="Member.Name"></span></td>
</tr>
<tr>
<th> <label asp-for="Member.Gender"></label></th>
<td>
<select asp-for="Member.Gender" class="form-control">
<option value="Male">Male</option>
<option value="Female">Female</option>
</select>
<span asp-validation-for="Member.Gender"></span>
</td>
</tr>
<tr>
<th> <label asp-for="Member.DOB"></label></th>
<td> <input asp-for="Member.DOB" class="form-control" placeholder="Enter animal category" /><span asp-validation-for="Member.DOB"></span></td>
</tr>
<tr>
<th> <label asp-for="Photo"></label></th>
<td>
<img src="~/ImageName/Cover/#Model.Member.ImageName"
class="rounded-square"
height="50" width="75"
style="border:1px"
asp-append-version="true" accept="image/*" />
<span>#Model.Member.ImageName</span>
<div id="chooseFile"><input type="file" name="photo" accept="image/*" /></div>
</td>
</tr>
<tr>
<th> <button type="submit" class="btn btn-primary" style="width:107px">Update</button></th>
<td> </td>
</tr>
<tr>
<th>#Html.ActionLink("Back To List", "MemberList", new { /* id=item.PrimaryKey */ }, new { #class = "btn btn-success" })</th>
<td> </td>
</tr>
</table>
</div>
</form>
</div>
Here make sure your src="~/ImageName/Cover/#Model.Member.ImageName" is correct as per your picture location. Otherwise picture will not be displayed
Controller When Submit Edit
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> EditMember(MemberViewModel model, IFormFile photo)
{
if (photo == null || photo.Length == 0)
{
return Content("File not selected");
}
//Save The Picture In folder
var path = Path.Combine(_environment.WebRootPath, "ImageName/Cover", photo.FileName);
using (FileStream stream = new FileStream(path, FileMode.Create))
{
await photo.CopyToAsync(stream);
stream.Close();
}
//Bind Picture info to model
model.Member.ImageName = photo.FileName;
//Finding the member by its Id which we would update
var objMember = _context.Members.Where(mId => mId.MemberId == model.Member.MemberId).FirstOrDefault();
if (objMember != null)
{
//Update the existing member with new value
objMember!.Name = model.Member.Name;
objMember!.Gender = model.Member.Gender;
objMember!.DOB = model.Member.DOB;
objMember!.ImageName = model.Member.ImageName;
objMember!.ImageLocation = path;
await _context.SaveChangesAsync();
}
return RedirectToAction("MemberList");
}
Here we will update the _context.SaveChangesAsync() instead of adding new data. This is the key point for edit. Update the information which we have got by ID
Output

Unable to pass view model list in CSHTML to controller

I have a View Model, View, and Controller that works great displaying the data, but I cannot get the data entered in the form to save to the controller. I've tried using a list, array, and a list for the view model.
Here's my view model:
public class AssignedHostData
{
public int HostID { get; set; }
public string HostName { get; set; }
public bool Assigned { get; set; }
[DisplayName("Additional Details")]
[DataType(DataType.MultilineText)]
public string AddDetails { get; set; }
}
Here's the section of my view that displays the data:
<table class="table">
<tr>
#{
int cnth = 0;
List<Support_Web.Models.ViewModels.AssignedHostData> hosts = ViewBag.Hosts;
foreach (var host in hosts)
{
if (cnth++ % 1 == 0)
{
#:</tr><tr>
}
#:<td>
<input type="checkbox"
name="selectedHosts[#cnth].HostID"
id="selectedHosts_[#cnth]_HostID"
value="#host.HostID"
#(Html.Raw(host.Assigned ? "checked=\"checked\"" : "")) />
#host.HostID #: #host.HostName
#:</td>
#:<td>
<input type="text" name="selectedHosts[#cnth].AddDetails" id="selectedHosts_[#cnth]_AddDetails" value="#host.AddDetails" />
#:</td>
}
#:</tr>
}
</table>
And here're the parameters from my Edit controller. The selectedProducts list returns an empty list every time:
public async Task<IActionResult> Edit(int? id, string[] selectedProducts, List<HostCheckListItem> selectedHosts)
My view needed to be formatted this way:
#{
int cnth = 0;
List<Support_Web.Models.ViewModels.AssignedHostData> hosts = ViewBag.Hosts;
for (int i = 0; i < hosts.Count; i++)
{
<tr>
<td>
<input type="checkbox"
name="selectedHosts[#i].HostID"
value="#hosts[#i].HostID"
#(Html.Raw(hosts[#i].Assigned ? "checked=\"checked\"" : "")) />
#hosts[#i].HostName
</td>
<td>
<input type="text" name="selectedHosts[#i].AddDetails" value="#hosts[#i].AddDetails" />
</td>
</tr>}
}
If you want to transfer the modified model data list in the view to
the controller, you can use "asp-for" to bind in the form.
Please refer to the following for details:
public class ProductController : Controller
{
private readonly MydbContext _context;
public ProductController (MydbContext context)
{
_context = context;
}
public IActionResult Index()
{
ViewBag.Hosts = _context.AssignedHostData.ToList();
return View();
}
public async Task<IActionResult> Edit(List<AssignedHostData> Hosts)
{
List<AssignedHostData> selectedHosts = Hosts.Where(x => x.Assigned == true).ToList();
return View();
}
}
Edit.cshtml:
<form asp-controller="Product" asp-action="Edit" method="post">
<table class="table">
<tr>
#{
int cnth = 0;
List<WebApplication_core.Models.AssignedHostData> Hosts = ViewBag.Hosts;
for (int i = 0; i < Hosts.Count; i++)
{
<tr>
<td>
<input id="Hidden1" type="hidden" asp-for="#Hosts[i].HostID" />
<input type="checkbox" asp-for="#Hosts[i].Assigned" />
#Hosts[i].HostName
<input id="Hidden2" type="hidden" asp-for="#Hosts[i].HostName" />
</td>
<td>
<input type="text" asp-for="#Hosts[i].AddDetails" />
</td>
</tr>
}
}
</table>
<input id="Button1" type="submit" value="Edit" />
</form>
Here is the debug result:

Asp.net core razor pages [BindProperty] doesnt work on collections

Im trying to use [BindProperty] annotation in asp.net core razor pages in order to Bind an Ilist<T> collection of one of my model classes so i can edit some of them at once, but it doesnt work at all, every time in OnPostAsync function the collection is empty, and neither the changes that i made on data nor it default values wont post back to the server, but when its a singel object [BindProperty] works fine and the values post back and can be changed, i also tried wraping a collection (i.e list<T>) in an object but it didnt work either way, so is there any way for doing so or i should lets say send a edit request for every object in that collection and edit them one by one(which cant be done in razor pages easilly and need some ajax calls)??
For binding IList between RazorPage and PageModel, you will need to use Product[i].Name to bind property.
Here are complete steps.
Model
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
}
PageModel
public class IndexModel : PageModel
{
private readonly CoreRazor.Data.ApplicationDbContext _context;
public IndexModel(CoreRazor.Data.ApplicationDbContext context)
{
_context = context;
}
[BindProperty]
public IList<Data.Product> Product { get; set; }
public async Task OnGetAsync()
{
Product = await _context.Product.ToListAsync();
}
public async Task OnPostAsync()
{
var product = Product;
}
}
View
<form method="post">
<table class="table">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.Product[0].Name)
</th>
<th></th>
</tr>
</thead>
<tbody>
#for (int i = 0; i < Model.Product.Count(); i++)
{
<tr>
<td>
<input hidden asp-for="Product[i].Id" class="form-control"/>
<input asp-for="Product[i].Name" class="form-control" />
</td>
<td>
<a asp-page="./Edit" asp-route-id="#Model.Product[i].Id">Edit</a> |
<a asp-page="./Details" asp-route-id="#Model.Product[i].Id">Details</a> |
<a asp-page="./Delete" asp-route-id="#Model.Product[i].Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</form>

MVC 4 model coming back null

So I have a view that requires several different objects and lists of objects to be passed in and out that I have created a viewmodel for. My viewmodel looks like this
public class EditUserViewModel
{
public ManageUsersViewModel ManageUsersViewModel { get; set; }
public IEnumerable<StateModel> StateModel { get; set; }
}
The part I'm having trouble with is the StateModel which looks like this
public class StateModel
{
public bool IsChecked { get; set; }
public States States { get; set; }
public UsersInStates UsersInStates { get; set; }
}
and contains this
[Table("States")]
public class States
{
[Key]
public int StateId { get; set; }
public string State { get; set; }
}
[Table("UsersInStates")]
public class UsersInStates
{
[Key, Column(Order = 1)]
public int UserId { get; set; }
[Key, Column(Order = 2)]
public int StateId { get; set; }
public string LicenseNumber { get; set; }
}
In my view I'm more or less trying to loop through the states and take user input for UsersInStates. This is how I'm trying to accomplish it but my entire StateModel comes back null. Going into the view the StateModel.States has data and the UsersInStates does not. This is what it looks like in my view
#foreach (var state in Model.StateModel)
{
#Html.HiddenFor(m => state)
<tr>
<td>
#Html.CheckBoxFor(m => state.IsChecked)
</td>
<td>
#Html.Label(state.States.State)
</td>
<td>
#Html.EditorFor(m => state.UsersInStates.LicenseNumber)
</td>
</tr>
}
Any advice would be much appreciated. Everything displays as it should and the ManageUsersViewModel part works fine it's just the StateModel data coming back to the controller is null and I'm not exactly sure how to make this work the way I'd like it to.
This is what the generated html looks like for the start of the table and the first row as requested
<table style="margin-left:auto; margin-right:auto; text-align:center">
<input id="state" name="state" type="hidden" value="WebSiteNew.Models.StateModel" /> <tr>
<td>
<input data-val="true" data-val-required="The IsChecked field is required." id="state_IsChecked" name="state.IsChecked" type="checkbox" value="true" /> <input name="state.IsChecked" type="hidden" value="false" />
</td>
<td>
<label for="Alabama">Alabama</label>
</td>
<td>
<input class="text-box single-line" id="state_UsersInStates_LicenseNumber" name="state.UsersInStates.LicenseNumber" type="text" value="" />
</td>
</tr>
Answer:
Ok so to solve this I used a for loop as explained in both references listed in the answer below
#for (int i = 0; i < Model.StateModel.Count(); i++)
{
<tr>
<td>
#Html.HiddenFor(m => m.StateModel[i].States.StateId)
#Html.HiddenFor(m => m.StateModel[i].States.State)
#Html.CheckBoxFor(m => m.StateModel[i].IsChecked)
</td>
<td>
#Html.Label(Model.StateModel[i].States.State)
</td>
<td>
#Html.EditorFor(m => m.StateModel[i].UsersInStates.LicenseNumber)
</td>
</tr>
}
Also a note to anyone looking at this, I had to change IEnumerable in my EditUsersViewModel to IList to allow for indexing.
So your issue is that the model binding isn't happening correctly.
Say you have these two models:
public class ParentModel
{
public string Name {get;set;}
public ChildModel Child {get;set;}
}
public class ChildModel
{
public string ChildName {get;set;}
public int SomeNumber {get;set;}
}
Your generated HTML (for your model binding to happen correctly) needs to look like this:
<input name="Name" value="(Not relevant to this example)"/>
<input name="Child.ChildName" value="(Not relevant to this example)" />
Note how the name field is structured - this is how MVC determines what input values map to which properties in your view model. With the nested property, the property name has to go in front of it.
With collections, it gets more complicated. The model binder needs to know which values go with which instance of a property.
For example, if we assume the ChildModel is of type IEnumerable in the previous example, your HTML might look something like this in order to model bind correctly:
<input name="Name" value="(Not relevant to this example)"/>
<input name="Child[0].ChildName" value="(Not relevant to this example)" />
<input name="Child[0].SomeNumber" value="(Not relevant to this example)"/>
<input name="Child[1].ChildName" value="(Not relevant to this example)" />
<input name="Child[1].SomeNumber" value="(Not relevant to this example)"/>
Take a look at these for how to fix it:
http://seesharpdeveloper.blogspot.com/2012/05/mvc-model-binding-to-list-of-complex.html
http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx
Edit - It's also important to note that when the Html Helpers generate the name value, it's based on the lambda value that is passed in. So
#Html.CheckBoxFor(m => state.IsChecked)
will generate the following name
name="state.IsChecked"
Since you're within a foreach, you're getting the wrong value for the name.
What are you trying to accomplish with the #Html.HiddenFor(m => state) - from the rendered HTML, that looks like your culprit right there. Would #Html.HiddenFor(m => state.StateId) be more appropriate?
Also, you could throw that into the first <td> element since it is hidden and will keep your HTML valid.

Parameter not passed to controller - Spring

I am at wits end here. This seems a very trivial thing but its not working. I have a jsp page that passes back to the server a Long (tournamentId) and a list of Objects.
When I post the form, the list is passed properly, but the Long member comes back as null, even though I can see it was sent.
The jsp:
<form:form method="post" action="addBets" modelAttribute="gwbCollection">
<c:choose>
<c:when test="${gwbCollection.tournamentState == 'CLOSED_FOR_BETS'}">
<br>
</c:when>
</c:choose>
<input name="tournamentId" value="${gwbCollection.tournamentId}" type="hidden"/>
<table>
<tr>
<td>Side A:</td>
<td>Score A:</td>
<td>Side B:</td>
<td>Score B:</td>
</tr>
<c:forEach var="gwb" items="${gwbCollection.games}" varStatus="status">
<tr>
<td><input name="games[${status.index}].game.gameId" value="${gwb.game.gameId}" type="hidden"/>
<input name="games[${status.index}].userId" value="${gwb.userId}" type="hidden"/>
<input name="games[${status.index}].game.tournamentId" value="${gwb.game.tournamentId}" type="hidden"/>
<input name="games[${status.index}].bet.betId" value="${gwb.bet.betId}" type="hidden"/>
${gwb.game.sideA}</td>
<td><input name="games[${status.index}].bet.scoreA" value="${gwb.bet.scoreA}"/></td>
<td>${gwb.game.sideB}</td>
<td><input name="games[${status.index}].bet.scoreB" value="${gwb.bet.scoreB}"/></td>
</tr>
</c:forEach>
</table>
<c:choose>
<c:when test="${gwbCollection.tournamentState == 'OPEN_FOR_BETS'}">
<input type="submit" />
</c:when>
</c:choose>
</form:form>
The Controller:
#Controller
#SessionAttributes
public class BetController {
...
#RequestMapping(value = "/addBets", method = RequestMethod.POST)
public String addBet(#ModelAttribute("gwbCollection") GamesWithBetsCollection gwbCollection) {
List<Bet> bets = gwbUtil.getBets(gwbCollection);
...
}
And finally, GamesWithBetsCollection:
public class GamesWithBetsCollection {
private TournamentState tournamentState;
private Long tournamentId;
private List<GameWithBet> games;
public GamesWithBetsCollection() {
}
public List<GameWithBet> getGames() {
return games;
}
public void setGames(List<GameWithBet> games) {
this.games = games;
}
public TournamentState getTournamentState() {
return tournamentState;
}
public void setTournamentState(TournamentState tournamentState) {
this.tournamentState = tournamentState;
}
public Long getTournamentId() {
return tournamentId;
}
public void setTournamentId(long tournamentId) {
this.tournamentId = tournamentId;
}
}
Nickdos - WOW! That is the answer! Beautiful catch!
To recap - the field "tournamentId" is defined as Long (object), but the setter has long (primitive) as parameter. Changing it to Long(object) did the trick.
Thanks again Nickdos!

Resources