Trouble getting textbox value from view to controller in ASP.NET MVC - c#

I'm still a beginner in ASP.NET MVC. I have a project that I am working on right now with two views and 1 controller. 1 scan page, 1 data entry page and 1 controller called LprController.
So on the data entry cshtml I have the button that I'm trying to get the data from called lotnoTBX.
div class="col-md-4 col-sm-offset-3">
<img src="~/Images/Capture.PNG" class="media-object center-block"/>
<div class="block-main col-sm-8 col-sm-offset-4">
<h2>Scan Lot</h2>
<input id="lotnoTBX"/>
<div class="container-fluid row">
<button id="enterBtn" type="submit" class="btn btn-primary btn-group-lg" style="margin-top:5px;" onclick="location.href='#Url.Action("DataEntry", "Lpr")'">Enter</button>
</div>
</div>
</div>
Then on the controller page things are a bit confusing. I'm not sure where to save or how to save the lotnoTBX data. Basically I'm using a webservice to get a query from the result of the textbox and post it to the dataentry page using Models.
public ActionResult ScanPage(FormCollection form)
{
string lotno = form["lotnoTBX"];
Session["lotno"] = lotno;
return View();
}
public ActionResult DataEntry()
{
FCoai.FCWCFT.PCSInterfaceClient client = new FCWCFT.PCSInterfaceClient("BasicHttpBinding_IPCSInterface1");
FCoai.FCWCFT.PCSResult x = client.getCurrentLotDetail(Session["lotno"].ToString());
return View();
}
Then here's the data entry page where I'm trying to post the model's in the cshtml.
<table>
<thead>
<tr>
<th class="table-active">OP</th>
<th class="table-active">Lotno</th>
<th class="table-active">Itemcode</th>
<th class="table-active">Marking</th>
<th class="table-active">Output</th>
</tr>
<tr>
<td #Model.op></td>
<td #Model.lotno></td>
<td #Model.itemCode></td>
<td #Model.marking></td>
<td #Model.output></td>
</tr>
</thead>
</table>
*edit I missed out one actionresult which might have been confusing for some people
Please help.

So I managed to get the textbox values to return. It turns out I had to use a form and a model as a parameter in the controller in order to do so.
Here's the scan lot cshtml
<h2>Scan Lot</h2>
#using (Html.BeginForm("ScanPage"))
{
#Html.TextBoxFor(Model => Model.lotno)
<input type="submit" value="Enter"/>
}
And here are the controllers
public ActionResult ScanPage()
{
return View();
}
[HttpPost]
public ActionResult ScanPage(FCoai.FCWCFT.PCSResult pCS)
{
string lotno = pCS.lotno;
Session["lotno"] = lotno;
return RedirectToAction("DataEntry", "Lpr");
}
public ActionResult DataEntry()
{
FCoai.FCWCFT.PCSInterfaceClient client = new FCWCFT.PCSInterfaceClient("BasicHttpBinding_IPCSInterface1");
FCoai.FCWCFT.PCSResult x = client.getCurrentLotDetail(TempData["lotno"].ToString());
//Passing data from controller to view
ViewData["Lot"] = x;
return View();
}
<div class="row">
<div class="col-md-12">
<table>
<thead>
<tr>
<th class="table-active">OP</th>
<th class="table-active">Lotno</th>
<th class="table-active">Itemcode</th>
<th class="table-active">Marking</th>
<th class="table-active">Routing</th>
</tr>
<tr>
#{
//This is how display data from view to controller
var lot = (FCoai.FCWCFT.PCSResult)ViewData["Lot"];
}
<td>#lot.op</td>
<td>#lot.lotno</td>
<td>#lot.itemCode</td>
<td>#lot.markLow</td>
<td>#lot.rout</td>
</tr>
</thead>
</table>
</div>
</div>
Edit here's my final answer.
Even though I have managed to find the answer to my own question I would appreciate if you guys could give tips on conventions or otherwise that I could have missed out on.

Related

MVC: Create does not work without #Html.EditorFor

I am currently trying to learn something about MVC by creating a small project. I already have managed to get a lot of things working, but now I am facing something I can not explain.
Basically, I have the usual setup (Model, Viewer, Controller) and my Model database is displayed in a View. Starting with the standard Create-View and -Action, which can be generated automatically in Visual Studio, I intended to change this method, so that some cells have calculated values and do not come from a user input.
This works fine for my Ready-column and Ready-Date-column, but fails for the Month-column. To generate a new row somehow
#Html.EditorFor(model => model.Month)
is needed. If I remove this (like I did for Ready and Ready-Date) clicking the submit-Button doesn't create anything and the application stays on the Create-Page.
My two ActionResults in the ModelController look like this:
public ActionResult Create()
{
//I use this in order to print the UpcomingMonth on the Create-Page
ViewBag.upcomingMonth = getUpcomingMonth();
return View();
}
public ActionResult Create([Bind(Include = "Report_ID,Month,Ready,Ready_Date")] Report report)
{
if (ModelState.IsValid)
{
//I would like to use this calculation for the Month-Value
report.Month = getUpcomingMonth();
//For Ready and Ready_Date it works to set the values here before adding to the db
report.Ready = true;
report.Ready_Date = System.DateTime.Now;
db.Reports.Add(report);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(report);
}
And the relevant part of my View:
<p style="float:right">
#*Button to create new month*#
#Html.ActionLink("Create", "Create")
</p>
<h2>Latest</h2>
<table class="table">
<thead>
<tr>
#*Column-header: Month*#
<th style="width: 10%; text-align:center">
#Html.DisplayNameFor(model => model.Month)
</th>
#*Column-header: True/False is ready*#
<th style="width: 10%; text-align:center">
#Html.DisplayNameFor(model => model.Ready)
</th>
#*Column-header: Set ready Date*#
<th style="width: 20%; text-align:center">
#Html.DisplayNameFor(model => model.Ready_Date)
</th>
</tr>
</thead>
<tbody>
<tr>
#*Cell: Latest Month*#
<td style="width: 10%; text-align:center">
#Html.DisplayFor(modelItem => Model.ElementAt(0).Month)
</td>
#*Cell: Latest True/False is ready
<td style="width: 10%; text-align:center">
...
</td>
#*Cell: Latest Set ready Date*#
<td style="width: 20%; text-align:center">
#Html.DisplayFor(modelItem => Model.ElementAt(0).Ready_Date)
</td>
</tr>
</tbody>
</table>
I really would appreciate any help!
PS: With ValidationSummary I get the following (no error message):
I think your view model doesn't validate. You can see what's error if you add these lines to view.
#Html.ValidationSummary(true, "Errors:", new { #class = "text-danger bg-danger" })
I finally found out what caused this behaviour.
In the setup of my model I defined a validation requirement, which did not allow an empty string. Because I set my data after I had checked ModelState.IsValid, the empty String did not pass this check and therefore the row wasn't added.
I solved it by removing the validation requirements of Month.

MVC submit button is always submitting the first record details on POST

I have a foreach loop in MVC page. like below. But, when I am submitting the form using submit button, it is always submitting the first record. Unable to understand why it is doing that way. Appreciate the help.
#model IEnumerable<DeployModel>
#using (Html.BeginForm("Index", "Dep", FormMethod.Post))
{
<div class="col-md-11">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-body" id="modal-body" style="overflow-y: auto">
#if (Model != null && Model.Any())
{
<div>
<table class="table table-condensed table-hover table-bordered">
<thead>
<th>
S1 Name
</th>
<th>
S2 Name
</th>
<th>
Old Version
</th>
<th>
New Version
</th>
<th>
Status
</th>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(o => item.S1)
</td>
<td>
#Html.DisplayFor(o => item.S2)
</td>
<td>
#Html.DisplayFor(o => item.OldVersion)
</td>
<td>
#Html.DisplayFor(o => item.NewVersion)
</td>
<td>
#Html.DisplayFor(o => item.Status)
</td>
<td>
<button name="SubmitButton" class="btn action-btn" type="submit" > Submit </button>
</td>
</tr>
}
</tbody>
</table>
</div>
}
</div>
</div>
</div>
</div>
}
My Controller action looks like as, but it is always receiving first record irrespective of button click.
[HttpPost]
public ActionResult Index(DeployModel deployModel)
{
//TODO code
}
Any idea how to resolve this?
There are a couple of problems here. The first is that Html.DisplayFor will just write the display string for the selected property's value with nothing telling the browser that it is form data to be submitted. The other is that all of your submit buttons are for the same form. There are a few ways to solve these problems. The one I would suggest is to create a separate form for each instance of DeployModel, and create hidden inputs for each property you are expecting to receive upon submission of the form:
// inside your foreach loop
#using (Html.BeginForm("Index", "Dep", FormMethod.Post))
{
<input type="hidden" name="S1" value="#item.S1" />
<input type="hidden" name="S2" value="#item.S2" />
...
<input type="submit" value="Submit" />
}
Also please note that if you use this method you should remove the outer form - you don't want nested forms!
You have to give a diffrent Name for each input.
exmaple
#Html.DisplayFor(o => item.S1, new { name = "input1" })

In an MVC Data List what is the best way to toggle conditions in a SQL Query

Please excuse me, I am new to MVC and Entity Framework but have been unable find information to solve my problem.
Problem 1 is that I am trying add a where statement to my model and show only active players. You can see my two separate procedures in my controller, but they both yield the same results.
public IActionResult ActivePlayers()
{
var model = _playerRepository.GetAllPlayers();
return View("Players",model.Where(d => d.IsActive = true));
}
public IActionResult AllPlayers()
{
var model = _playerRepository.GetAllPlayers();
return View("Players", model);
}
My second problem is I am having a hard time figuring how to toggle between All Players and Active ones from the View.
I tried the following, but quickly realized that it wouldn't work since the page is re-rendered after calling the controller. - Note, I was using jQuery to toggle viability.
<div>
<label id="lblShowAll" style="color:green;font-style:italic;font-weight:bold;"
>Showing Active Players</label>
<label id="lblLimitList" style="color:green;font-style:italic;font-weight:bold;display:none;"
>Showing All Players</label>
<br />
<a id="ShowAll" class="btn btn-link"
asp-controller="admin" asp-action="allPlayers">Show All Players</a>
<a id="LimitList" class="btn btn-link" style="display:none;"
asp-controller="admin" asp-action="activePlayers">Limit List (Active Players)</a>
</div>
I'm not sure it matters but this is what my data list looks like in the View.
<div class="container" id="players">
<br />
<div style="width:90%; margin:0 auto;">
<table id="playerList" class="table table-striped table-bordered dt-responsive nowrap"
width="100%" cellspacing="0">
<thead>
<tr>
<th>Name</th>
<th>Address</th>
<th>City</th>
<th>State</th>
<th>Telephone</th>
<th>Edit</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
#foreach (var player in Model)
{
<tr>
<th>#player.Name</th>
<th>#player.Address</th>
<th>#player.City</th>
<th>#player.State</th>
<th>#player.Telephone</th>
<th>
<a class="btn btn-outline-info m-1"
asp-controller="admin" asp-action="editPlayer" asp-route-id="#player.PlayerId">
Edit</a>
</th>
<th>
<a class="btn btn-outline-danger m-1">Delete</a>
</th>
</tr>
}
</tbody>
</table>
</div>
</div>
Thanks in advance!

Row to send a List<Object> from Razor page to Update?

I need to send a List back to my controller and update the values on my repository.
But after load the view with the values, update it and click the submit button, I don't know how to get the list with the update values and call the update method from the repository.
I'm using .Net 4.7.2.
HomeController:
[HttpGet]
public ActionResult Nota(string Concurso)
{
List<InscricoesModel> model = new List<InscricoesModel>();
InscricoesRepository repository = new InscricoesRepository();
model = repository.GetAprovadosPrimeiraFase(new Guid(Concurso));
return View("Nota",model);
}
[HttpPost]
public void UdateNotas(List<InscricoesModel> model)
{
InscricoesRepository repository = new InscricoesRepository();
foreach(InscricoesModel item in model)
{
repository.Update(item);
}
}
Nota.cshtml:
#model List<ConcursoBolsaSegundaFase.Model.InscricoesModel>
<h1>Classificados 2ª Fase</h1>
<hr />
<p>Exportado em #DateTime.Now</p>
<div style="margin-top:15px">
#* TABELA RESULTADO *#
<div id="notasAprovadosSegundaFase" style="margin-top:10px">
#using (Html.BeginForm("UdateNotas", "Home", Model, FormMethod.Post))
{
<table class="table table-bordered" id="tblNotaAprovadosSegundaFase">
<thead>
<tr>
<th>Inscrição</th>
<th>Nome</th>
<th>Nota Primeira Fase</th>
<th>Fez Carta</th>
<th>Nota Segunda Fase</th>
</tr>
</thead>
<tbody>
#if (Model != null)
{
foreach (var linha in Model)
{
<tr>
<td>#linha.Inscricao</td>
<td>#linha.Nome</td>
<td>#linha.NotaPrimeiraFase</td>
<td>
<select>
<option value="false">Não</option>
<option value="true">Sim</option>
</select>
</td>
<td><input type="text" value="#linha.NotaSegundaFase"></td>
</tr>
}
}
</tbody>
</table>
<button type="submit" class="btn btn-success">Salvar</button>
}
</div>
</div>
The UpdateNotas method in my controller never recive a value, i don't know how to send the list from the view to my controller.
In MVC, the name of the input will be binded to the variable in the controller. In your case, your input has no name. I suggest you look at the html helpers.
This would bind your values properly.
for (int i = 0;i<Model.Count;i++)
{
Html.TextBoxFor(model => Model[i].NotaSegundaFase)
}
In this case, only NotaSegundaFase would be sent back to the controller.
You can use #Html.HiddenFor() to hold the data on the view and bind to controller on Post.
#using (Html.BeginForm("UdateNotas", "Home", Model, FormMethod.Post))
{
<table class="table table-striped table-bordered table-sm table-responsive">
<thead>
<tr>
<th>Inscrição</th>
<th>Nome</th>
<th>Nota Primeira Fase</th>
<th>Fez Carta</th>
<th>Nota Segunda Fase</th>
</tr>
</thead>
<tbody>
#for (int i = 0; i < Model.Count; i++)
{
#Html.HiddenFor(model => Model[i].Inscrição)
#Html.HiddenFor(model => Model[i].Nome)
#Html.HiddenFor(model => Model[i].NotaPrimeiraFase)
<tr>
<td>#Model[i].Inscrição</td>
<td>#Model[i].Nome</td>
<td>#Model[i].NotaPrimeiraFase</td>
#*do this similary for other property *#
</tr>
}
</tbody>
</table>
<button type="submit" class="btn btn-success">Salvar</button>
}
As far as I understood,you want to post DropDownList value only.
if you decide to update other fields just add the Html.Editor into the loop like following.
#Html.Editor("[" + i + "].Inscricao")
#Html.Editor("[" + i + "].Nome")
I hope this will help.
#using (Html.BeginForm("UdateNotas", "Home", Model, FormMethod.Post))
{
<table class="table table-bordered" id="tblNotaAprovadosSegundaFase">
<thead>
<tr>
<th>Inscrição</th>
<th>Nome</th>
<th>Nota Primeira Fase</th>
<th>Fez Carta</th>
<th>Nota Segunda Fase</th>
</tr>
</thead>
<tbody>
#if (Model != null)
{
#for (int i = 0; i < Model.Count; i++)
{
<tr>
<td>#Model[i].Inscrição</td>
<td>#Model[i].Nome</td>
<td>#Model[i].NotaPrimeiraFase</td>
<td>
<select name="[#i].NotaSegundaFase">
<option value="false">Não</option>
<option value="true">Sim</option>
</select>
</td>
<td><input type="text" value="#linha.NotaSegundaFase"></td>
</tr>
}
}
</tbody>
</table>
<button type="submit" class="btn btn-success">Salvar</button>
}
Note : don't change anything in the controller. model binder should resolve everything from the request.

Linq refer to list of objects which were passed with an include statement

Here is how I pass a model to a view:
public ActionResult Public()
{
db = new Entities();
var regions = db.Regions.Include(d => d.Days);
return View(regions.ToList());
}
Now I want to be able to create a foreach in the view which will access the collection of days I included in regions for that particular region. Is there a way to do this through link or should I create a seperate ViewModel that contains fields separately for Regions and for Days?
part of view code:
...
#for(int i = 1; i < Model.Count(); i ++){
<div id="_page_#i" class="frame" style="display: block;">
<p>
<button style="width:70px" type="button">Add +</button>
</p>
<p>
<table class="table striped bordered hovered" >
<thead>
<tr>
<th class="text-left">Title</th>
<th class="text-left">Date</th>
<th class="text-left"> </th>
</tr>
</thead>
<tbody>
#foreach(var item in Model){
<tr class="">
<td>#item</td>
<td class="right"></td>
<td class="right" style="width: 180px; height: 35px"><button style="width:159px; height: 32px" type="button">Delete -</button></td>
</tr>
}
</tbody>
</table>
</p>
</div>
}
</div>
</div>
</div>
</div>
I need the foreach to refer to the Days in the Regions so that item would be one Day.
In your view you do a foreach within a foreach. In my example, it will creale a list of Days for all Regions... assuming the Day has a property "Name":
<ul>
#foreach( var r in Model){
foreach( var d in r.Days){
<li>d.Name</li>
}
}
</ul>

Categories