Drop Down list null reference on postback ASP.Net Core 6 MVC - drop-down-menu

I have spent a lot of time trying to sort this out without any luck.
I have successfully created a drop down list and it populates the field and all is well. It even posts the record back to the database. But upon clicking the submit button I get a Null Reference error.
Any and all help would be very appreciated
Below is the Model Code
using Microsoft.AspNetCore.Mvc;
using System.Data.SqlClient;
namespace CISIII.Models
{
public class Dropdownlist
{
public DateTime? DtmDate { get; set; }
public List<Status_List>? Statlist2 { get; set; }
public IActionResult? GetDetails { get; set; }
}
public class Status_List
{
public int Id { get; set; }
public string? Description { get; set; }
}
public class UserDataModel
{
public string? Fname { get; set; }
public string? Sname { get; set; }
public string? Coname { get; set; }
public string? Tel { get; set; }
public string? Email { get; set; }
public string? Add1 { get; set; }
public string? Add2 { get; set; }
public string? Suburb { get; set; }
public string? State { get; set; }
public string? Pcode { get; set; }
public string? Findus { get; set; }
public string? Prod_cat { get; set; }
public string? Question2 { get; set; }
public string? Ddlindustry { get; set; }
public string? Web { get; set; }
public string? Statlist1 { get; set; }
public string? Start_date { get; set; }
public string? End_date { get; set; }
public int SaveDetails()
{
SqlConnection con = new SqlConnection("Data Source=bhd-web2;User ID=**;Password=**;Database=***; Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False");
string query = "INSERT INTO Customers (fname, sname, coname, tel, email, add1, add2, suburb, state, pcode, " +
"findus, prod_cat, question2, ddlindustry, web, status, start_date, end_date, entry_date) values ('" + Fname + "','" + Sname + "','" + Coname + "', " +
"'" + Tel + "','" + Email + "','" + Add1 + "','" + Add2 + "','" + Suburb + "','" + State + "','" + Pcode + "','" + Findus + "','" + Prod_cat + "', " +
"'" + Question2 + "','" + Ddlindustry + "','" + Web + "','" + Statlist1 + "','" + Start_date + "','" + End_date + "', getdate())";
SqlCommand cmd = new SqlCommand(query, con);
con.Open();
int i = cmd.ExecuteNonQuery();
con.Close();
return i;
}
}
}
Below is the Controller Code
using Microsoft.AspNetCore.Mvc;
using CISIII.Models;
using System.Data.SqlClient;
namespace CISIII.Controllers
{
public class HomeController : Controller
{
public IConfigurationRoot GetConnection()
{
var builder = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appSettings.json").Build();
return builder;
}
public IActionResult Index()
{
Dropdownlist multi_Dropdownlist = new Dropdownlist
{
Statlist2 = GetStatusList()
};
return View(multi_Dropdownlist);
}
public List<Status_List> GetStatusList()
{
var connection = GetConnection().GetSection("ConnectionStrings").GetSection("CAS").Value;
SqlConnection con = new SqlConnection(connection);
SqlCommand cmd = new SqlCommand("Select id, description From status order by description asc;", con);
con.Open();
SqlDataReader idr = cmd.ExecuteReader();
List<Status_List> status = new List<Status_List>();
if (idr.HasRows)
{
while (idr.Read())
{
status.Add(new Status_List
{
Id = Convert.ToInt32(idr["id"]),
Description = Convert.ToString(idr["description"]),
});
}
}
con.Close();
return status;
}
public IActionResult View1()
{
return View();
}
public IActionResult Privacy()
{
return View();
}
public IActionResult newcust()
{
Dropdownlist multi_Dropdownlist = new Dropdownlist
{
Statlist2 = GetStatusList(),
};
return View(multi_Dropdownlist);
}
[HttpPost]
public IActionResult GetDetails()
{
UserDataModel umodel = new UserDataModel();
umodel.Fname = HttpContext.Request.Form["fname"].ToString();
umodel.Sname = HttpContext.Request.Form["sname"].ToString();
umodel.Coname = HttpContext.Request.Form["coname"].ToString();
umodel.Tel = HttpContext.Request.Form["tel"].ToString();
umodel.Email = HttpContext.Request.Form["email"].ToString();
umodel.Add1 = HttpContext.Request.Form["street_number"].ToString();
umodel.Add2 = HttpContext.Request.Form["route"].ToString();
umodel.Suburb = HttpContext.Request.Form["locality"].ToString();
umodel.State = HttpContext.Request.Form["administrative_area_level_1"].ToString();
umodel.Pcode = HttpContext.Request.Form["postal_code"].ToString();
umodel.Findus = HttpContext.Request.Form["Findlist"].ToString();
umodel.Prod_cat = HttpContext.Request.Form["Prodlist"].ToString();
umodel.Question2 = HttpContext.Request.Form["question2"].ToString();
umodel.Ddlindustry = HttpContext.Request.Form["ddlindustry"].ToString();
umodel.Web = HttpContext.Request.Form["web"].ToString();
umodel.Statlist1 = HttpContext.Request.Form["Statlist"].ToString();
umodel.Start_date = HttpContext.Request.Form["start_date"].ToString();
umodel.End_date = HttpContext.Request.Form["end_date"].ToString();
int result = umodel.SaveDetails();
return View("newcust");
}
}
}
Below is the View
#model CISIII.Models.Dropdownlist
#addTagHelper*, Microsoft.AspNetCore.Mvc.TagHelpers
#{
ViewData["Title"] = "New Customer";
}
<head>
<table style="margin:0 auto;" >
<tr >
<td ><label>First Name</label></td>
<td >
<input class="field" id="fname" name="fname" TabIndex="1"/>
</td>
<td ><label>Address</label></td>
<td TabIndex="8">
<div id="locationField">
<input id="autocomplete"
placeholder="Enter your address"
onFocus="geolocate()"
type="text"/>
</div>
<td></td>
</td>
</tr>
<tr>
<td ><label>Surname</label></td>
<td >
<input class="field" id="sname" name="sname" TabIndex="2"/></td>
<td ><label>Address 2</label></td>
<td Width="8">
<input class="field" id="street_number" name="street_number" disabled="disabled" />
<input class="field" id="route" name="route" disabled="disabled"/>
</td>
</tr>
<tr>
<td><label>Company Name</label></td>
<td><input class="field" id="coname" name="coname"/></td>
<td><label>Suburb</label></td>
<td>
<input class="field" id="locality" name="locality" disabled="disabled"/>
</td>
</tr>
<tr>
<td><label>Tel No</label></td>
<td>
<input class="field" id="tel" name="tel" TabIndex="4"/></td>
<td><label>State</label></td>
<td>
<input class="field" id="administrative_area_level_1" name="administrative_area_level_1" disabled="disabled"/>
</td>
</tr>
<!-- Communication Details for the Client -->
<tr>
<td ><label>Email</label></td>
<td><input id="email" class="field" name="email" TabIndex="5"/></td>
<td><label>Post Code</label></td>
<td >
<input class="field" id="postal_code" name="postal_code" disabled="disabled"/>
</td>
<!-- OnTextChanged="date_insert" -->
</tr>
<tr>
<td ><label>Web</label></td>
<td >
<input id="web" class="field" name="web" TabIndex="6"></td>
<td ><label>Status</label></td>
<td>
<div id="Status" name="Status">
</div>
<div class="col-md-5">
#Html.DropDownListFor(x => x.Statlist2, new SelectList(Model.Statlist2, "Description", "Description"), htmlAttributes: new { #class = "form-control"})
</div>
</td>
</tr>
<tr >
<td ><label>Start Date</label></td>
<td >
<input id="start_date" name="start_date" class="start_date">
</td>
<td ><label>End Date</label></td>
<td >
<input id="end_date" name="end_date" class="end_date">
</td>
</tr>
<!-- Asking Questions of the client -->
<tr >
<td ColumnSpan="4">
<Label>How did you hear about Us</Label>
</td>
</tr>
<tr >
<td >
<Label>Industry</Label>
</td>
<td ColumnSpan="3" Style="" >
<div class="col-md-3">
</div>
</td>
</tr>
<tr >
<td >
<Label>Product Category</Label>
</td>
</tr>
<tr >
<td >
<Label>Where did you find us</Label>
</td>
</tr>
<tr>
<td ColumnSpan="4" >
<Label>Customer Notes</Label>
</td>
<td ColumnSpan="4" >
<textarea id="question2" class="field" name="question2" cols="40" rows="5"></textarea>
</td>
</tr>
<tr>
<td ColumnSpan="2" ><input id="Submit" type="submit" value="submit" formaction="GetDetails" asp-page-handler="Submit"/>
</td>
</tr>
</table>
</form>
#section Scripts{
<script type="text/javascript">
$(function () {
$(".form-control").chosen();
});
</Script>
<script type="text/javascript">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script>
$(".start_date").datepicker({
dateFormat: 'dd/mm/yy',
chanegMonth: true,
changeYear: true,
minDate: new Date(2019,01,01),
maxDate: new Date(2032,01,01),
});
$(".end_date").datepicker({
dateFormat: 'dd/mm/yy',
chanegMonth: true,
changeYear: true,
minDate: new Date(2019,01,01),
maxDate: new Date(2032,01,01),
});
</script>
}
The Error
An unhandled exception occurred while processing the request.
NullReferenceException: Object reference not set to an instance of an object.
AspNetCoreGeneratedDocument.Views_Home_newcust.ExecuteAsync() in newcust.cshtml, line 230
Stack Query Cookies Headers Routing
NullReferenceException: Object reference not set to an instance of an object.
AspNetCoreGeneratedDocument.Views_Home_newcust.ExecuteAsync() in newcust.cshtml
#Html.DropDownListFor(x => x.Statlist2, new SelectList(Model.Statlist2, "Description", "Description"), htmlAttributes: new { #class = "form-control"})
Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageCoreAsync(IRazorPage page, ViewContext context)
Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageAsync(IRazorPage page, ViewContext context, bool invokeViewStarts)
Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderAsync(ViewContext context)
Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, string contentType, Nullable<int> statusCode)
Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, string contentType, Nullable<int> statusCode)
Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ActionContext actionContext, IView view, ViewDataDictionary viewData, ITempDataDictionary tempData, string contentType, Nullable<int> statusCode)
Microsoft.AspNetCore.Mvc.ViewFeatures.ViewResultExecutor.ExecuteAsync(ActionContext context, ViewResult result)
Microsoft.AspNetCore.Mvc.ViewResult.ExecuteResultAsync(ActionContext context)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResultFilterAsync>g__Awaited|30_0<TFilter, TFilterAsync>(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext<TFilter, TFilterAsync>(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

Related

ASP.NET Routes config not following tutorial

I'm trying to follow a basic tutorial to get forms working:
https://www.completecsharptutorial.com/asp-net-mvc5/4-ways-to-create-form-in-asp-net-mvc.php
After running the first example my code trying to render localhost:5001/form1 instead of the example's localhost:5001/Home/form1
I'm assuming the issue is my Starup.cs routes needs to be tweaked. It currently looks like:
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
Controller code:
namespace test_ops.Controllers
{
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
}
public IActionResult Index()
{
return View();
}
public IActionResult Privacy()
{
return View();
}
[ResponseCache(Duration = 0, Location =
ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId =
Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
[HttpPost]
public ActionResult form1(int txtId, string txtName, string chkAddon)
{
ViewBag.Id = txtId;
ViewBag.Name = txtName;
if (chkAddon != null)
ViewBag.Addon = "Selected";
else
ViewBag.Addon = "Not Selected";
return View("Index");
}
}
}
Model code:
namespace test_ops.Models
{
public class TestModel
{
[Required]
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Addon { get; set; }
}
}
View code in Home/index.cshtml:
<h4 style="color:purple">
<b>ID:</b> #ViewBag.ID <br />
<b>Name:</b> #ViewBag.Name <br />
<b>Addon:</b> #ViewBag.Addon
</h4>
<hr />
<h3><b>Forms: Weakly Typed</b></h3>
<form action="form1" method="post">
<table>
<tr>
<td>Enter ID: </td>
<td><input type="text" name="txtId" /></td>
</tr>
<tr>
<td>Enter Name: </td>
<td><input type="text" name="txtName" /></td>
</tr>
<tr>
<td>Addon: </td>
<td><input type="checkbox" name="chkAddon" /></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="Submit Form" /></td>
</tr>
</table>
</form>
After submitting the form the page comes back with the a 404:
"This localhost page can’t be foundNo webpage was found for the web address: https://localhost:5001/form1
HTTP ERROR 404"
Can someone please let me know what needs to be changed to get this working?
try to add controller to your form
<form action="#Url.Action("form1", "home")" method="post">
...
but is much better to use this syntax instead of form
#using (Html.BeginForm("form1", "Home", FormMethod.Post))
{
<table>
<tr>
//...
<tr>
<td colspan="2"><input type="submit" value="Submit Form" /></td>
</tr>
}
and check a file _ViewImports.cshtml in a View folder. It should have
#addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

Posted ViewModel return null properties

I am having issues with a view model that constantly return null properties after a post. Below is my code (it could be a syntax issue or two calling a class or property the same name as i saw in other posts but i could not see any such issue in code):
VIEW MODEL:
public class ProductItem
{
public int ProductID { get; set; }
public string Code { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string LongDescription { get; set; }
public int SupplierID { get; set; }
public string Dimensions { get; set; }
public double Price { get; set; }
public bool On_Sale { get; set; }
public double DiscountedPrice { get; set; }
public string Thumbnail { get; set; }
public string LargeImage { get; set; }
public string LargeImage2 { get; set; }
public string LargeImage3 { get; set; }
public string CrossRef { get; set; }
public byte Available { get; set; }
public double Weight { get; set; }
public byte Important { get; set; }
public virtual ICollection<ProductCategory> ProductCategories { get; set; }
// this is required on the page to allow products to be marked for deletion
public bool IsForDelete { get; set; }
}
public class ProductListViewModel
{
public IEnumerable<ProductItem> ProductItems { get; set; }
public IEnumerable<Category> CategoryItems { get; set; }
}
CONTROLLER:
public ActionResult ProductList()
{
var productList = new ProductListViewModel();
productList.ProductItems = productRepository.GetProductsWithDeleteOption().ToList();
productList.CategoryItems = categoryRepository.GetCategories().ToList();
return View(productList);
}
[HttpPost]
public ActionResult ProductList(ProductListViewModel productViewModel, FormCollection formCollection, string submit)
{
if (ModelState.IsValid)
{
// Check for submit action
if (submit == "Change Sort")
{
if (formCollection["Sortby"] == "ProductID")
{
OrderBy(productViewModel, formCollection, "m.ProductID");
}
else if (formCollection["Sortby"] == "Code")
{
OrderBy(productViewModel, formCollection, "m.Code");
}
else if (formCollection["Sortby"] == "Name")
{
OrderBy(productViewModel, formCollection, "m.Name");
}
else if (formCollection["Sortby"] == "Price")
{
OrderBy(productViewModel, formCollection, "m.Price");
}
}
else if (submit == "Delete all selected")
{
}
else if (submit == "Update All")
{
}
else if (submit == "Restrict Display")
{
}
}
return View(productViewModel);
}
VIEW:
#model Admin.Models.ViewModels.ProductListViewModel
#{
ViewBag.Title = "View Products";
}
#using (Html.BeginForm())
{
<h2>Product List as at #DateTime.Now.ToString("dd/MM/yyyy")</h2>
<table>
<tr>
<td>Sort by:</td>
<td>
<select name="Sortby">
<option value="ProductID">ProductID</option>
<option value="Code">Code</option>
<option value="Name">Name</option>
<option value="Price">Price</option>
</select>
</td>
<td>
<input type="radio" name="sortDirection" checked="checked" value="Asc" /> Ascending
<input type="radio" name="sortDirection" value="Desc" /> Descending
</td>
<td>
<input type="submit" name="submit" value="Change Sort" />
</td>
</tr>
<tr>
<td>Display only : (category)</td>
<td>#Html.DropDownList("CategoryID", new SelectList(Model.CategoryItems, "CategoryID", "Name"), "All Categories")</td>
<td colspan="2"><input type="submit" name="submit" value="Restrict Display" /></td>
</tr>
<tr>
<td colspan="4"><br />Total Number of products: #Model.ProductItems.Count()</td>
</tr>
</table>
<table>
<tr>
<th>
Edit
</th>
<th>
Code
</th>
<th>
Name
</th>
<th>
Price
</th>
<th>
On_Sale
</th>
<th>
DiscountedPrice
</th>
<th>
Weight
</th>
<th>
Delete
</th>
<th></th>
</tr>
#for (var i = 0; i < Model.ProductItems.ToList().Count; i++)
{
<tr>
<td>
#Html.HiddenFor(m => m.ProductItems.ToList()[i].ProductID)
#Html.ActionLink(Model.ProductItems.ToList()[i].ProductID.ToString(), "ProductEdit", new { id = Model.ProductItems.ToList()[i].ProductID })
</td>
<td>
#Html.DisplayFor(m => m.ProductItems.ToList()[i].Code)
</td>
<td>
#Html.DisplayFor(m => m.ProductItems.ToList()[i].Name)
</td>
<td>
#Html.EditorFor(m => m.ProductItems.ToList()[i].Price)
</td>
<td>
#Html.CheckBoxFor(m => m.ProductItems.ToList()[i].On_Sale, new { id = "On_Sale_" + Model.ProductItems.ToList()[i].ProductID })
</td>
<td>
#Html.EditorFor(m => m.ProductItems.ToList()[i].DiscountedPrice)
</td>
<td>
#Html.EditorFor(m => m.ProductItems.ToList()[i].Weight)
</td>
<td>
#Html.CheckBoxFor(m => m.ProductItems.ToList()[i].IsForDelete, new { id = Model.ProductItems.ToList()[i].ProductID })
</td>
<td>
#Html.ActionLink("Edit", "ProductEdit", new { id = Model.ProductItems.ToList()[i].ProductID }) |
#Html.ActionLink("Details", "Details", new { id = Model.ProductItems.ToList()[i].ProductID }) |
#Html.ActionLink("Delete", "Delete", new { id = Model.ProductItems.ToList()[i].ProductID })
</td>
</tr>
}
</table>
<p>
<input name="submit" type="submit" value="Delete all selected" />
</p>
<p>
<input name="submit" type="submit" value="Update All" />
</p>
<p>
#Html.ActionLink("Add a new product", "ProductAdd")
</p>
}
In the post action, the productViewModel argument has the ProductItems and CategoryItems properties as null.
Ok, so there are two problems.
I don't understand why you want to post list of the CategoryItems You should only expect the selected category and not the list
The problem with ProductItems is the name generated for <input> tags. Currently, the name being generated is name="[0].Price" whereas it should have been name="ProductItems[0].Price"
I changed the following code
#Html.EditorFor(m => m.ProductItems.ToList()[i].Price)
to
#Html.EditorFor(m => m.ProductItems[i].Price)
and it worked.
Note: I changed IEnumerable<ProductItem> ProductItems to List<ProductItem> ProductItems in ProductListViewModel
Yes it will be null on post back. I have a similar table in one of my projects and this is what I would have done given my situation.
You could change your view model to look like this then you don't have to do so many converting to lists in your view:
public class ProductListViewModel
{
public List<ProductItem> ProductItems { get; set; }
public List<Category> CategoryItems { get; set; }
}
Now in you view it could look something like this (this is just part of it, then rest you can just go and add):
#for (int i = 0; i < Model.ProductItems.Count(); i++)
{
<tr>
<td>
#Html.DisplayFor(m => m.ProductItems[i].Name)
#Html.HiddenFor(m => m.ProductItems[i].Name)
</td>
</tr>
<tr>
<td>
#Html.CheckBoxFor(m => m.ProductItems[i].IsForDelete)
</td>
</tr>
}
Add the code and do some debugging to see how the values are returned on submit
I hope this helps.

I lost my data on submit MVC 3

I have a MVC 3 application with entity framework.
In my page I use a custom Model that contains all objects I use. The page is rendered perfectly, but when I press the submit button my object loses the data.
This is my custom model:
public class ControleAcessoModel
{
private List<Controle> controles = new List<Controle>();
public GRUPO_ACESSO_TB grupo_acesso_tb { get; set; }
public List<Controle> Controles
{
get
{
return controles;
}
}
public void AddTela(byte id, string nome)
{
Controle ctrl = new Controle();
ctrl.ID_TELA = id;
ctrl.NM_TELA = nome;
controles.Add(ctrl);
}
public class Controle
{
public bool Selecionado { get; set; }
public byte ID_TELA { get; set; }
public string NM_TELA { get; set; }
public bool FL_SALVAR { get; set; }
public bool FL_ALTERAR { get; set; }
public bool FL_EXCLUIR { get; set; }
}
}
this is my Razor Html code:
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<table>
<tr>
<th>Salvar</th>
<th>Editar</th>
<th>Excluir</th>
<th>Tela</th>
</tr>
#foreach (var item in Model.Controles)
{
<tr>
<td style="text-align: center">
#Html.EditorFor(modelItem => item.FL_SALVAR)
</td>
<td style="text-align: center">
#Html.EditorFor(modelItem => item.FL_ALTERAR)
</td>
<td style="text-align: center">
#Html.EditorFor(modelItem => item.FL_EXCLUIR)
</td>
<td>
#Html.DisplayFor(modelItem => item.NM_TELA)
</td>
</tr>
}
</table>
<p>
<input type="submit" value="Salvar" />
</p>
}
This is my create code, where I put the data on database.
Is in this part, that my object controleacessomodel is empty.
[HttpPost]
public ActionResult Create(ControleAcessoModel controleacessomodel, byte id)
{
if (ModelState.IsValid)
{
for (int i = 0; i < controleacessomodel.Controles.Count; i++)
{
if (ValidaSelecao(controleacessomodel.Controles[i]))
{
PERMISSAO_GRUPO_ACESSO_TELA_TB permissao = new PERMISSAO_GRUPO_ACESSO_TELA_TB();
permissao.ID_GRUPO_ACESSO = controleacessomodel.grupo_acesso_tb.ID_GRUPO_ACESSO;
permissao.ID_TELA = controleacessomodel.Controles[i].ID_TELA;
permissao.FL_SALVAR = controleacessomodel.Controles[i].FL_SALVAR;
permissao.FL_ALTERAR = controleacessomodel.Controles[i].FL_ALTERAR;
permissao.FL_EXCLUIR = controleacessomodel.Controles[i].FL_EXCLUIR;
db.PERMISSAO_GRUPO_ACESSO_TELA_TB.AddObject(permissao);
}
}
db.SaveChanges();
return RedirectToAction("Edit", "GrupoAcesso", new { id = id });
}
return View(controleacessomodel);
}
Why my object is empty after submit?
It's not possible to use the Foreach loop construct as the generated ids will be not be correct, therefore MVC is not able to map the values back to the model. You need to use a for loop instead:
#for (int i = 0 ; i < Model.Controles.Count; i++)
{
<tr>
<td style="text-align: center">
#Html.EditorFor(m => m.Controles[i].FL_SALVAR)
</td>
<td style="text-align: center">
#Html.EditorFor(m => m.Controles[i].FL_ALTERAR)
</td>
<td style="text-align: center">
#Html.EditorFor(m => m.Controles[i].FL_EXCLUIR)
</td>
<td>
#Html.DisplayFor(m => m.Controles[i].NM_TELA)
</td>
</tr>
}
Phil Haack write a good blog post about this. Also Scott Hanselman wrote a nice post too.

How to pass IEnumerable object or data from view to controller?

I have created a strongly type view. I want to pass IEnumerable Object or data from View to Controller. Following are my Model, Controller ,view
My Model:
public class UserDetailsClass
{
public static FeedbackDatabaseDataContext context = new FeedbackDatabaseDataContext();
public class Tablefields
{
[Key]
public int ID { get; set; }
[Required(ErrorMessage = "Email is required")]
public string EmailID { get; set; }
[Required(ErrorMessage="Password is required")]
public string Password { get; set; }
[Required(ErrorMessage = "First Name is required")]
public string FirstName { get; set; }
[Required(ErrorMessage = "Last Name is required")]
public string LastName { get; set; }
}
public static List<UserDetails> getalluser()
{
var lst = (from r in context.UserDetails select r);
return lst.ToList();
}
}
My Controller
public ActionResult Test()
{
IList<UserDetailsClass.Tablefields> viewmodel = new List<UserDetailsClass.Tablefields>();
var q = UserDetailsClass.getalluser().ToList();
foreach (SQLOperation.Models.UserDetails item in q)
{
UserDetailsClass.Tablefields viewItem = new UserDetailsClass.Tablefields();
viewItem.EmailID = item.Email;
viewItem.FirstName = item.FirstName;
viewItem.LastName = item.LastName;
viewItem.Password = item.Password;
viewmodel.Add(viewItem);
}
return View(viewmodel);
}
[HttpPost]
public ActionResult Test(IEnumerable<UserDetailsClass.Tablefields> items)
{
return View();
}
My View:
#model IEnumerable<SQLOperation.Models.UserDetailsClass.Tablefields>
#{
ViewBag.Title = "Test";
}
<h2>Test</h2>
#using (Html.BeginForm())
{
<table>
<tr>
<th>
EmailID
</th>
<th>
Password
</th>
<th>
FirstName
</th>
<th>
LastName
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.EmailID)
</td>
<td>
#Html.DisplayFor(modelItem => item.Password)
</td>
<td>
#Html.DisplayFor(modelItem => item.FirstName)
</td>
<td>
#Html.DisplayFor(modelItem => item.LastName)
</td>
</tr>
}
</table>
<input type="submit" value="submit" />
}
I didn't get any value in items.When I set breakpoint on it it show NULL in items
I am totally Confused about how to pass values to controller.
Thank you,
Amol
Instead of #Html.DisplayFor use #Html.EditorFor, that way databinding will happen in your form.
Also since you are using collection you need to iterate your fields (simplified example):
#for (int row = 0; row < Model.Count; row++)
{
#Html.EditorFor(x => x[row].FirstName )
}
#for (int i = 0; i < Model.length; i ++)
{
<tr>
<td>
#Html.DisplayFor(model => Model[i].EmailID)
</td>
<td>
#Html.DisplayFor(model => Model[i].Password)
</td>
<td>
#Html.DisplayFor(model => Model[i].FirstName)
</td>
<td>
#Html.DisplayFor(model => Model[i].LastName)
</td>
</tr>
}
</table>
<input type="submit" value="submit" />
}

Parameters from view not getting to controller action method

I'm implementing Troy Goode's PagedList in one of my views (ASP.NET MVC 3 Razor). The challenge I'm having is when I click on a page number link, the request is routed to my HttpGet method, which just returns the empty page (ready for input).
My View Model:
public class SearchViewModel
{
public SelectList IndustrySelectList { get; set; }
public IPagedList<KeyValuePair<string, SearchResult>> SearchResults { get; set; }
public PagingInfo PagingInfo { get; set; }
}
Controller:
[HttpGet]
public ViewResult Search(string searchTerm = "")
{
SearchViewModel vm = new SearchViewModel
{
IndustrySelectList = new SelectList(_Industries.AsEnumerable(), "IndustryId", "IndustryName"),
PagingInfo = new PagingInfo
{
CurrentPage = 1,
ItemsPerPage = 25,
TotalItems = 0
}
};
return View(vm);
}
[HttpPost]
public ActionResult Search(string[] industries, string searchTerm = "", int page = 1)
{
SearchViewModel vm = null;
_url = "http://localhost/MasterNode/masternode.cgi?zoom_query={" + searchTerm + "}&zoom_xml=1&zoom_page={startPage?}&zoom_per_page=1000";
StringBuilder sb = new StringBuilder();
int pageSize = 5;
if (string.IsNullOrEmpty(searchTerm))
{
vm = new SearchViewModel
{
IndustrySelectList = new SelectList(_Industries.AsEnumerable(), "IndustryId", "IndustryName")
};
}
else
{
_request = new SearchRequest(SearchRequest.EnvironmentTypes.Development, "", _url, searchTerm, SearchRequest.SearchType.AllWords, 1000);
sb.Append(GetResults(_url));
_results = new Dictionary<string, SearchResult>();
ParseResults(sb);
GetDetailInformationForResults(searchTerm);
vm = new SearchViewModel
{
IndustrySelectList = new SelectList(_Industries.AsEnumerable(), "IndustryId", "IndustryName"),
SearchResults = _results.ToList<KeyValuePair<string, SearchResult>>().ToPagedList(1, 25),
PagingInfo = new PagingInfo
{
CurrentPage = page,
ItemsPerPage = pageSize,
TotalItems = _results.Count()
}
};
}
return View(vm);
}
View:
#model MultiView.OmniGuide.ViewModels.SearchViewModel
#using MultiView.OmniGuide.HtmlHelpers
#using PagedList
#using PagedList.Mvc
#{
ViewBag.Title = "Search";
}
<link href="/Content/PagedList.css" rel="stylesheet" type="text/css" />
#using (Html.BeginForm("Search", "Home"))
{
#Html.HiddenFor(c => c.IndustrySelectList)
#Html.HiddenFor(c => c.PagingInfo)
#Html.HiddenFor(c => c.SearchResults)
<table width="70%">
<tr>
<td colspan="2" style="background: #fff">
<input id="searchTerm" name="searchTerm" type="text" class="SearchBox" style="width: 450px" />
<input type="submit" class="SearchButton" value=" " />
</td>
</tr>
<tr align="left">
<td align="left" style="background: #fff">
#Html.ActionLink("MultiView corporate site", "Search")
</td>
</tr>
<tr>
<td colspan="1" align="center" style="width: 450px">
#{
Html.Telerik().PanelBar()
.Name("searchPanel")
.Items(title =>
{
title.Add()
.Text("Filter by Industry")
.Content(() =>
{
#Html.RenderPartial("_Industry", #Model);
});
})
.Render();
}
</td>
</tr>
<tr><td colspan="2"></td></tr>
</table>
<br />
if (Model.SearchResults != null)
{
<table width="70%">
<tr>
<th>
Company Image
</th>
<th class="tableHeader">
Company Name Here
</th>
<th class="tableHeader">
Website
</th>
</tr>
#foreach (KeyValuePair<string, MultiView.OmniGuide.Models.SearchResult> itm in Model.SearchResults)
{
<tr>
<td align="left" style="width: 15%">
#itm.Value.DetailedInfo.LogoURL
</td>
<td align="left" style="width: 60%">
<p style="text-align: left">
#itm.Value.DetailedInfo.DescriptionAbbreviated
<br />
</p>
#Html.AnchorLink(itm.Value.FoundURL, itm.Value.FoundURL)
</td>
<td style="width: 25%">
#itm.Value.FoundURL
</td>
</tr>
}
</table>
#Html.PagedListPager((IPagedList)Model.SearchResults, page => Url.Action("Search", "Home", new { page }))
}
}
When text is supplied in the input box and the button is clicked, the requested is routed to the HttpPost method. In looking at the request.form values, all expected data but paging information is present.
?HttpContext.Request.Form.AllKeys
{string[5]}
[0]: "IndustrySelectList"
[1]: "PagingInfo"
[2]: "SearchResults"
[3]: "searchTerm"
[4]: "industries"
Any help with this would be very much appreciated!
By clicking the button you are submitting the form which is why it is doing the httppost. The next page link is hitting the httpget correctly but you are not passing it any information to so that it knows what to get. The get needs other information, like what page you are wanting.
The page number links fire a GET request, so you'll need to make sure that your GET action can handle the full search as well, so will need to get the page number and industries array - using defaults for when those parameters aren't available.
e.g.
[HttpGet]
public ViewResult Search(string searchTerm = "", int page = 1,
string industries = "")
{
//.....
}
You'll need to modify the pager link like this to pass industries to the get action.
#Html.PagedListPager((IPagedList)Model.SearchResults, page => Url.Action("Search", "Home", new { page, industries = string.Join(",", Model.IndustrySelectList.Where( x => x.Selected).Select( x => x.Text)) }))
It's not clear to me from your code where the post action is getting string[] industries from, or what it is doing with it, but you will need some way of passing this same this to your get action, probably as a single string that is comma separated. The example I've provided assumed you are taken it from the select list on the viewmodel

Resources