MVC navigating from Index to enhanced Edit view - asp.net-mvc

I have a simple Index view, where I am displaying products as a product catalog.
ViewModel:
public class Products
{
public int ID { get; set; }
public int CategoryID { get; set; }
public string ProductName { get; set; }
public string ProductDescription { get; set; }
public string ProductPicturePath { get; set; }
public string UnitCost { get; set; }
public string UnitPrice { get; set; }
public string LowestUnitPrice { get; set; }
public string SubscriptionPrice { get; set; }
public string UnitMargin { get; set; }
public string UnitProfit { get; set; }
public bool InCatalog { get; set; }
}
View:
#using freshNclean.Models
#model IEnumerable<freshNclean.Models.Products>
#{
ViewBag.Title = "Sortiment";
}
<div id="productCatalogContainer" class="container">
<div id="productCatalogHeaderSection" class="headerSection">
<h1 id="productCatalogHeaderTitle" class="headerTitle">
#ViewBag.Title
</h1>
<i id="productCatalogHeaderIcon" class="headerIcon fas fa-gem" aria-hidden="true"></i>
</div>
<!-- table section -->
<section id="productCatalogListPartialSection" class="table">
<div id="productCatalogSeparatorSection" class="separatorSection">
<hr id="productCatalogSeparator" class="separator" />
</div>
<div id="productCatalog" class="productTableSection row">
#foreach (var item in Model)
{
if (item.InCatalog == true)
{
<a id="productCatalogProductArea" class="tableArea col-xs-offset-1 col-xs-10 col-sm-offset-1 col-sm-10 col-md-offset-2 col-md-3 col-lg-offset-2 col-lg-3" href="#Url.Action("Details", "ShowProduct", new { id = item.ID })">
#Html.HiddenFor(modelItem => item.ID, new { #class = "tableField col-xs-12 col-sm-12 col-md-12 col-lg-12" })
<img id="productCatalogProductImage" class="tableImage col-xs-12 col-sm-12 col-md-12 col-lg-12" src="#Url.Content(item.ProductPicturePath)" alt="Produktbild" />
<div id="productCatalogProductNameField" class="tableField col-xs-12 col-sm-12 col-md-12 col-lg-12">
#Html.DisplayFor(modelItem => item.ProductName)
</div>
<div id="productCatalogProductDescriptionField" class="tableField col-xs-12 col-sm-12 col-md-12 col-lg-12">
#Html.DisplayFor(modelItem => item.ProductDescription)
</div>
<div id="productCatalogLowestUnitPriceField" class="tableField col-xs-12 col-sm-12 col-md-12 col-lg-12">
ab #Html.DisplayFor(modelItem => item.LowestUnitPrice)
</div>
</a>
}
}
</div>
<div id="productCatalogListPartialMenuSeparatorSection" class="separatorSection">
<hr id="productCatalogListPartialMenuSeparator" class="separator" />
</div>
#Html.ActionLink("zum Warenkorb", "ShowShoppingCart", "", htmlAttributes: new { #class = "formButton col-xs-offset-1 col-xs-10 col-sm-offset-1 col-sm-10 col-md-offset-3 col-md-6 col-lg-offset-3 col-lg-6" })
</section>
</div>
<!-- link back to menu -->
<div id="productCatalogReturnToMenuSection" class="linkSection">
#Html.ActionLink("zurück zum Menü", "Profile", "", htmlAttributes: new { #id = "productCatalogReturnToMenuButton", #class = "link" })
</div>
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
<!-- Google Places -->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBYK8aBCsb1dFrzXqIgUq07ZwO3w3_fGCs&libraries=places&callback=initAutocomplete" async defer></script>
}
Controller:
// GET: /freshNclean/ProductCatalog
public ActionResult ProductCatalog()
{
// define variables
var userID = User.Identity.GetUserId();
DateTime nowUTC = DateTime.Now.ToUniversalTime();
DateTime nowLocal = DateTime.Now.ToLocalTime();
// pass first name to viewbag for personalization
//ViewBag.Personalization = UserManager.FindById(userID).FirstName.ToString();
// track user activity: get method is restricted to activity name and timestamp
var LOADED = new UserActivities
{
UserID = userID,
ActivityName = "ProductCatalog_Loaded",
ActivityTimeStampUTC = nowUTC,
ActivityLatitude = "n/a",
ActivityLongitude = "n/a",
ActivityLocation = "n/a"
};
DATADB.UserActivityList.Add(LOADED);
DATADB.SaveChanges();
return View(DATADB.ProductList.Where(x => x.InCatalog == true).OrderBy(x => x.ProductName).ToList());
}
This all works fine.. but now I wish to click on an individual product to display a new view with details of the product and the possibility to define order quantity.
New VM:
public class ProductViewModel
{
public int ProductID { get; set; }
public string ProductName { get; set; }
public string ProductDescription { get; set; }
public string ProductPicturePath { get; set; }
[RegularExpression(#"^\((\d{3}?)\)$", ErrorMessage = "Du brauchst die Anzahl nicht ausschreiben - verwende Ziffern.")]
[Display(Name = "Bestellmenge")]
public string SubscriptionQuantity { get; set; }
[Display(Name = "Lieferrhytmus")]
public string SubscriptionCadenceCategory { get; set; }
public string SubscriptionCadenceValue { get; set; }
[Display(Name = "Preis im Abonnement")]
public string SubscriptionPrice { get; set; }
public bool IsSingleOrder { get; set; }
[RegularExpression(#"^\((\d{3}?)\)$", ErrorMessage = "Du brauchst die Anzahl nicht ausschreiben - verwende Ziffern.")]
[Display(Name = "Bestellmenge")]
public string Quantity { get; set; }
[Display(Name = "Preis pro Einheit")]
public string UnitPrice { get; set; }
public DateTime ActivityDateTime { get; set; }
public string ActivityLatitude { get; set; }
public string ActivityLongitude { get; set; }
public string ActivityLocation { get; set; }
}
Now, where I got stuck is how I would display the new, enhanced model - the issue I run into is that with the standard approach, clicking a product in the product catalog is creating something like /ShowProduct/5 in the URL, but that would force me to use the same view model in the details view as in the catalog, which is not what I want/need. If anyone has an idea how to solve this, I'd highly appreciate your input. Also, please note that I am an absolute beginner, hence examples are highly appreciated. Thank you!

Related

MVC Net 6 Get Object from SelectList using its id

Hello i am triying to figure out how to get the object after is selected in the selectlist, the selectlist holds the "Id" field and "Code" field, but i want to get access to the other fields of the object after is selected. I would like to show the "Amount" field and the "Coin.Name" of the object in the view after the selecction.
Order Model
public class Order
{
[Required]
[Key]
public int Id { get; set; }
[ForeignKey("Id")]
[Display(Name = "Proveedor")]
public int ProviderId { get; set; }
[Display(Name = "Proveedor")]
public virtual Provider Provider { get; set; } = null!;
[ForeignKey("Id")]
[Display(Name = "Pais")]
public int CountryId { get; set; }
[Display(Name = "Pais")]
public virtual Country Country { get; set; } = null!;
[ForeignKey("Id")]
[Display(Name = "Categoria")]
public int CategoryId { get; set; }
[Display(Name = "Categoria")]
public virtual Category Category { get; set; } = null!;
[Required]
[StringLength(100)]
[Display(Name = "Coigo de Orden")]
public string Code { get; set; } = null!;
[Required]
[Display(Name = "Moneda")]
public int CoinId { get; set; }
[Display(Name = "Moneda")]
public virtual Coin Coin { get; set; } = null!;
[Required]
[Display(Name = "Monto")]
[Precision(18, 2)]
public decimal Amount { get; set; }
[Required]
[DisplayFormat(DataFormatString = "{0:dd-MM-yyyy}", ApplyFormatInEditMode = true)]
[Display(Name = "Fecha")]
public DateTime Date { get; set; }
[Required]
[DisplayFormat(DataFormatString = "{0:dd-MM-yyyy}", ApplyFormatInEditMode = true)]
[Display(Name = "Fecha Tope")]
public DateTime DateEnd { get; set; }
[ForeignKey("Id")]
[Display(Name = "Comprador")]
public int BuyerId { get; set; }
[Display(Name = "Comprador")]
public virtual Buyer Buyer { get; set; } = null!;
[StringLength(500)]
[Display(Name = "Comentarios")]
public string Comments { get; set; }
[StringLength(500)]
[Display(Name = "Campo 1")]
public string Field1 { get; set; }
[StringLength(500)]
[Display(Name = "Campo 2")]
public string Field2 { get; set; }
[StringLength(500)]
[Display(Name = "Campo 3")]
public string Field3 { get; set; }
[StringLength(500)]
[Display(Name = "Campo 4")]
public string Field4 { get; set; }
[ForeignKey("Id")]
public int AuditUserId { get; set; }
public virtual User AuditUser { get; set; } = null!;
public DateTime AuditDateTime { get; set; }
public bool AuditDelete { get; set; }
}
Coin Model
public class Coin
{
[Required]
[Key]
public int Id { get; set; }
[Required]
[StringLength(100)]
[Display(Name = "Nombre")]
public string Name { get; set; }
[ForeignKey("Id")]
public int AuditUserId { get; set; }
public virtual User AuditUser { get; set; } = null!;
[Required]
public DateTime AuditDateTime { get; set; }
[Required]
public bool AuditDelete { get; set; }
}
Create Controller
public async Task<IActionResult> Create(int idPayment)
{
ViewData["id"] = idPayment;
ViewData["OrderId"] = new SelectList(_context.Orders.Include(o => o.Coin).Where(x => x.AuditDelete == false).OrderBy(x => x.Code), "Id", "Code");
ViewData["PaymentStatusId"] = new SelectList(_context.PaymentsStatus.Where(x => x.AuditDelete == false).OrderBy(x => x.Status), "Id", "Status");
return View();
}
Create View
#model WebApplicationDailyPayments.Models.Database.PaymentDetails
#{
ViewData["Title"] = "Crear";
}
<h1>Crear</h1>
<h4>Detalle de pagos</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="PaymentId" class="control-label"></label>
<select asp-for="PaymentId" class ="form-control" asp-items="ViewBag.PaymentId"></select>
</div>
<div class="form-group">
<label asp-for="OrderId" class="control-label"></label>
<select asp-for="OrderId" class ="form-control" asp-items="ViewBag.OrderId"></select>
</div>
<div class="form-group">
<label asp-for="PaymentStatusId" class="control-label"></label>
<select asp-for="PaymentStatusId" class ="form-control" asp-items="ViewBag.PaymentStatusId"></select>
</div>
<div class="form-group">
<label asp-for="AmountPaid" class="control-label"></label>
<input asp-for="AmountPaid" class="form-control" id="AmountPaid" />
<span asp-validation-for="AmountPaid" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Rate" class="control-label"></label>
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="rateChecked" checked="">
<label class="form-check-label" for="flexSwitchCheckChecked">Multiplicar - Dividir</label>
</div>
<input asp-for="Rate" class="form-control" id="Rate"/>
<span asp-validation-for="Rate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="AmountPaidFinal" class="control-label"></label>
<input asp-for="AmountPaidFinal" class="form-control" id="AmountPaidFinal" readonly />
<span asp-validation-for="AmountPaidFinal" class="text-danger"></span>
</div>
<br/>
<div class="form-group">
<input type="submit" value="Crear" class="btn btn-primary" /> <a class="btn btn-primary" asp-action="Index" asp-route-idPayment="#ViewData["id"]">Regresar a la Lista</a>
</div>
</form>
</div>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
<script>
$(function(){
$("#AmountPaid,#Rate").keyup(function (e) {
var q=$("#AmountPaid").val().toString().replace(",",".");
var p = $("#Rate").val().toString().replace(",", ".");
var c = document.getElementById('rateChecked');
var result=0;
if(q!=="" && p!=="" && $.isNumeric(q) && $.isNumeric(p))
{
if(c.checked)
{
result = parseFloat(q) * parseFloat(p);
}
else
{
result = parseFloat(q) / parseFloat(p);
}
}
$("#AmountPaidFinal").val((Math.round(result * 100) / 100).toString().replace(".", ","));
});
});
</script>
}
Edit 1
I added in the controller to pass the Orders to the view
ViewData["Orders"] = _context.Orders.Include(o => o.Coin).Where(x => x.AuditDelete == false).ToList();
I added in the view to get the orders
#{
foreach (var item in (IEnumerable<WebApplicationDailyPayments.Models.Database.Order>)(ViewData["Orders"]))
{
var a = item.Id;
}
}
Now i get the Orders in the view, now i need to filter by Id selecetd in the selectlsit
Thank you
You can monitor select changes to perform corresponding operations.
Below is my test code, you can refer to it.
In the view, I use JavaScript to monitor whether the select changes, so as to obtain the selected Id for matching:
<div class="form-group">
<label asp-for="OrderId" class="control-label"></label>
<select id="my_select" asp-for="OrderId" class="form-control" asp-items="#ViewBag.OrderId"></select>
</div>
<script>
$("#my_select").change(function () {
var id = $(this).children(":selected").attr("value");
var array = #Html.Raw(Json.Serialize(ViewData["Orders"]));
for (var i = 0; i < array.length; i++) {
if(array[i].id == parseInt(id))
{
console.log("Coin.Name:"+array[i].coin.name);
console.log("Amount:" + array[i].amount);
}
}
});
</script>
Test Result:
Is this what you want?

Retrieving data from one-to-many associated table with ASP.Net Core

I have an asp.net core mvc 3.1 project. There is user management in this project. The user table and the department table are linked by one to many relationships (I'm not sure I did this correctly). I can get the user registration smoothly. However, I can not show the department name in the table that I use on the front side according to the departmentId value I added while getting the registration of the user from the department table that I have established.
I need your support in this regard.
Note: I'm using ReflectionIT.Mvc.Paging
AppDbContext
public class AppDbContext : IdentityDbContext<AppUser, AppRole, string>
{
public AppDbContext(DbContextOptions<AppDbContext> options)
: base(options)
{
}
public DbSet<AppUser> Kullanicilar { get; set; }
public DbSet<Firma> Firmalar { get; set; }
public DbSet<Departman> Departmanlar { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
//kullanıcı tablolarında kullanmak istemediğim tablalrı kaldırma
modelBuilder.Entity<AppUser>()
.Ignore(p => p.PhoneNumber)
.Ignore(p => p.PhoneNumberConfirmed);
}
}
AppUser Model
public class AppUser : IdentityUser<string>
{
public string Ad { get; set; }
public string Soyad { get; set; }
public string Gorevi { get; set; }
public string Image { get; set; }
public string GsmNo { get; set; }
public string KanGrubu { get; set; }
public string DepartmanId { get; set; }
public Departman Departman { get; set; }
public virtual ICollection<Departman> DepartmanListesi { get; set; }
}
Departman Model
public class Departman
{
[StringLength(450)]
[Index(IsUnique = true)]
public string Id { get; set; }
[Required]
[Display(Name ="Departman Adı")]
public string Name { get; set; }
}
RegisterViewModel
public class RegisterViewModel
{
[Required(ErrorMessage = "Bu alan zorunludur!")]
[EmailAddress]
[Display(Name = "Email Adres:")]
[Remote(action:"IsEmailInUse", controller:"Account")]
[ValidEmailDomain(allowedDomain:"bakirlar.com.tr", ErrorMessage = "Sadece bakirlar.com.tr uzantılı email adresi ile kayıt olabilirsiniz.")]
public string Email { get; set; }
[Required(ErrorMessage = "Bu alan zorunludur!")]
[DataType(DataType.Password)]
[Display(Name = "Şifre:")]
public string Password { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Şifre Onayı:")]
[Compare("Password",ErrorMessage = "Şifreler Eşleşmiyor!")]
public string ConfirmPassword { get; set; }
[Required(ErrorMessage = "Bu alan zorunludur!")]
[Display(Name = "Ad:")]
public string Ad { get; set; }
[Required(ErrorMessage = "Bu alan zorunludur!")]
[Display(Name = "Soyad:")]
public string Soyad { get; set; }
[Required(ErrorMessage = "Bu alan zorunludur!")]
[Display(Name = "Görevi:")]
public string Gorevi { get; set; }
[Required(ErrorMessage = "Bu alan zorunludur!")]
[Display(Name = "GSM No:")]
public string GsmNo { get; set; }
[Required(ErrorMessage = "Bu alan zorunludur!")]
[Display(Name = "Kan Grubu:")]
public string KanGrubu { get; set; }
[Required(ErrorMessage = "Bu alan zorunludur!")]
[Display(Name = "Departman:")]
public string DepartmanId { get; set; }
public Departman Departman { get; set; }
}
AccountController
Action => AddNewUser
[HttpPost]
[Authorize(Roles = "Admin")]
public async Task<IActionResult> AddNewUser(RegisterViewModel model)
{
if (ModelState.IsValid)
{
Departman newDepartmanId = departmanRepository.GetById(model.DepartmanId);
var user = new AppUser
{
UserName = model.Email,
Email = model.Email,
Ad = model.Ad,
Soyad = model.Soyad,
GsmNo = model.GsmNo,
Gorevi = model.Gorevi,
KanGrubu = model.KanGrubu,
Departman = newDepartmanId,
};
user.Id = Guid.NewGuid().ToString();
var result = await userManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
if (signInManager.IsSignedIn(User) && User.IsInRole("Admin"))
{
return RedirectToAction("ListUsers", "Administration");
}
await signInManager.SignInAsync(user, isPersistent: false);
return RedirectToAction("Index", "Home");
}
foreach (var error in result.Errors)
{
ModelState.AddModelError("", error.Description);
}
}
return View(model);
}
AdministrationController
Action => ListUsers
public async Task<IActionResult> ListUsers(string filter, int page = 1, int satir = 10, string sortExpression = "UserName")
{
ViewBag.SayfaAdi = "Kullanıcı Listesi";
var item = userManager.Users.AsNoTracking()
.AsQueryable();
if (!string.IsNullOrWhiteSpace(filter))
{
item = item.Where(p => p.UserName.ToLower().Contains(filter.ToLower()));
}
var model = await PagingList.CreateAsync(item, satir, page, sortExpression, "UserName");
model.RouteValue = new RouteValueDictionary
{
{"filter", filter}
};
return View(model);
}
View => ListUsers
#model PagingList<AppUser>
<div class="container-fluid page__heading-container">
<div class="page__heading d-flex align-items-center">
<div class="flex">
<nav aria-label="breadcrumb">
<ol class="breadcrumb mb-0">
<li class="breadcrumb-item"><i class="material-icons icon-20pt">home</i></li>
<li class="breadcrumb-item active" aria-current="page">#ViewBag.SayfaAdi</li>
</ol>
</nav>
<h1 class="m-0">Kullanıcı Listesi</h1>
</div>
<a asp-action="AddNewUser" asp-controller="Account" class="btn btn-success ml-3 text-white">Yeni Kullanıcı<i class="material-icons icon-16pt text-white">add</i></a>
</div>
</div>
<!--Tablo Arama Alanı Başlangıç-->
<div class="card card-form d-flex flex-column flex-sm-row">
<form method="get" class="card-form__body card-body-form-group flex">
<div class="row">
<div class="col-sm-12">
<div class="form-group">
<label for="filter_name">Kullanıcı Adı</label>
<div class="search-form form-control search-form--light input-group-lg">
<input id="filter" name="filter" type="text" class="form-control" placeholder="Kullanıcı Adına Göre Ara..." value="#Model.RouteValue["filter"]">
<button id="clear" class="btn btn-hover-primary" type="button" role="button" onclick="ClearTextBox()">Temizle</button>
</div>
<button style="display:none" type="submit"></button>
</div>
</div>
</div>
</form>
</div>
<!--Tablo Arama Alanı Bitiş-->
<!--Tablo Başlangıcı-->
<div id="view-all">
#await Html.PartialAsync("_ViewAllUsers", Model)
</div>
<!--Tablo Bitişi-->
<!--Pagination-->
<div class="d-flex flex-row align-items-center">
<div class="form-inline">
<vc:pager paging-list="#Model" />
</div>
</div>
<!--Pagination-->
PartialView => _ViewAll
#model PagingList<AppUser>
<div class="card">
<div class="table-responsive">
<table class="table mb-0 thead-border-top-0 table-striped table-bordered table-hover">
<thead>
<tr>
<th class="text-center" style="width: 30px;">#ID</th>
<th style="width: auto;">Kullanıcı Adı ve Email</th>
<th style="width: auto;">Ad Soyad</th>
<th style="width: auto;">Departman</th>
<th style="width: auto;">Görevi</th>
<th style="width: auto;">GSM No</th>
<th class="text-center">İşlem</th>
</tr>
</thead>
<tbody class="list" id="tumKullanicilar">
<!--Veriler Başlangıç-->
#foreach (var user in Model)
{
<tr>
<td>
<div class="badge badge-light">##user.Id</div>
</td>
<td>#user.Email</td>
<td>#user.Ad #user.Soyad</td>
<td>
#foreach (var departman in user.DepartmanListesi)
{
#departman.Name
}
</td>
<td>#user.Gorevi</td>
<td>#user.GsmNo</td>
<td class="text-center" style="width: 95px;">
<button onclick="showInPopup('#Url.Action("AddOrEdit","Account",new {id=user.Id},Context.Request.Scheme)','Kullanıcı Bilgilerini Düzenle')" class="btn btn-primary p-1"><i class="material-icons icon-16pt text-white">edit</i></button>
<form asp-action="Delete" asp-route-id="#user.Id" onsubmit="return jQueryAjaxDelete(this)" class="d-inline">
<button type="submit" value="X" class="btn btn-danger p-1"><i class="material-icons icon-16pt text-white">delete_forever</i></button>
</form>
</td>
</tr>
}
<!--Veriler Bitiş-->
</tbody>
</table>
</div>
</div>
SQL Server DB Screen Shot
The table AppUser only store DepartmanId when finished registration.
If you want to show Departman Info, you should add Departman to each AppUser.
public async Task<IActionResult> ListUsers(string filter, int page = 1, int satir = 10, string sortExpression = "UserName")
{
ViewBag.SayfaAdi = "Kullanıcı Listesi";
var item = userManager.Users.AsNoTracking()
.AsQueryable();
if (!string.IsNullOrWhiteSpace(filter))
{
item = item.Where(p => p.UserName.ToLower().Contains(filter.ToLower()));
}
//**** add Departman to each User
// var userList = item.ToList();
// for (int i = 0; i < userList.Length; i++)
// userList[i].Departman = departmanRepository.GetById( userList[i].DepartmanId);
var model = await PagingList.CreateAsync(item, satir, page, sortExpression, "UserName");
model.RouteValue = new RouteValueDictionary
{
{"filter", filter}
};
return View(model);
}

MVC Subitem list

I am trying to create an entity that has subitems and am having issues with passing the model back and forth.
I have an entity RiskAssessnent that contains a list of Risk entities.
public class RiskAssessment
{
public int Id { get; set; }
public DateTime Date { get; set; }
public ICollection<Risk> Risks { get; set; }
public int ResidentId { get; set; }
public Resident Resident { get; set; }
public int EmployeeId { get; set; }
public Employee Employee { get; set; }
}
public class Risk
{
public int Id { get; set; }
public string Description { get; set; }
public int RiskAssessmentId { get; set; }
public RiskAssessment RiskAssessment { get; set; }
}
here is my view for creating a RiskAssessment:
#model CareHomeMvc6.Models.RiskAssessmentViewModels.RiskAssessmentViewModel
#{
ViewData["Title"] = "Create";
}
<a class="btn btn-default" asp-action="Index" asp-route-residentId="#Model.ResidentId">Back to List</a>
<div class="page-header">
<h1>Create a Risk Assessment</h1>
</div>
<form asp-action="Create">
<div class="form-horizontal">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
#Html.HiddenFor(m => m.EmployeeId)
#Html.HiddenFor(m => m.ResidentId)
<div class="form-group">
<label asp-for="Date" class="col-md-2 control-label"></label>
<div class="col-md-10">
#Html.EditorFor(m => m.Date, new { #class = "form-control" })
<span asp-validation-for="Date" class="text-danger" />
</div>
</div>
#foreach(var risk in Model.Risks)
{
<h3>#risk.Description</h3>
}
<p>
<a class="btn btn-success" asp-action="CreateRisk">Create</a>
</p>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
</form>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
and here is the controller:
public IActionResult CreateRisk(RiskAssessmentViewModel riskAssessmentViewModel)
{
var vm = new CreateRiskViewModel
{
RiskAssessment = riskAssessmentViewModel,
Risk = new Risk()
};
return View(vm);
}
and the ViewModel:
public class RiskAssessmentViewModel
{
public RiskAssessmentViewModel()
{
this.Risks = new List<Risk>();
this.Risks.Add(new Risk
{
Id = 1,
Description = "blah",
PotentialRisk = "blah"
});
}
public int Id { get; set; }
[Display(Name = "Date")]
[DataType(DataType.Date)]
[Required]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime Date { get; set; }
public ICollection<Risk> Risks { get; set; }
public int ResidentId { get; set; }
public int EmployeeId { get; set; }
}
Sorry for all the code so far!
I was attempting to keep passing the ViewModel back and forth until all items have been created but within the CreateRisk action the ResidentId and EmployeeId are 0 therefore not being set, although I do get the collection of risks. If I click submit on the form which encapsulates everything then they are set. Is there any reason the hidden items are being sent to the form submit but not the link action?
I realise there are JS solutions to doing dynamic lists but I wanted to stay away from it as the page navigation is acceptable, the form will when finished require a lot of data entry for a Risk.
Any help with this would be greatly appreciated.
Thanks

Error in my upload page after i changed my model [duplicate]

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 6 years ago.
I added the code to show many checkboxes from my table (HairTags) and in my form CreationUpload.cshtml i got the following error :
An exception of type 'System.NullReferenceException' occurred in
App_Web eba142hb.dll but was not handled in user code Additional
information: Object reference not set to an instance of an object.
Object reference not set to an instance of an object.
<div class="col-md-12">
#for (int i = 0; i < Model.CreationHairTags.Count; i++)
{
#Html.CheckBoxFor(m => Model.CreationHairTags[i].IsChecked)
#Model.CreationHairTags[i].Text
#Html.HiddenFor(m => Model.CreationHairTags[i].Value)
#Html.HiddenFor(m => Model.CreationHairTags[i].Text)<br />
}
</div>
this is my model Creation.cs (in bold the added code)
namespace HairCollection3.Models
{
public class Creation
{
public string UserId { get; set; }
[Key]
public int CreationId { get; set; }
[Required(ErrorMessageResourceName = "Required", ErrorMessageResourceType = typeof(ViewRes.ValidationStrings))]
[Display(Name = "Sex", ResourceType = typeof(ViewRes.Names))]
public string CreationSex { get; set; }
[Required(ErrorMessageResourceName = "Required", ErrorMessageResourceType = typeof(ViewRes.ValidationStrings))]
[Display(Name = "CreationTitle", ResourceType = typeof(ViewRes.NamesCreation))]
[StringLength(2000)]
[AllowHtml]
public string CreationTitle { get; set; }
public string CreationPhotoBis { get; set; }
public string Creationtag { get; set; }
public virtual ICollection<CreationLike> CreationLikes { get; set; }
}
public class CreationLike
{
public int CreationId { get; set; }
public string UserId { get; set; }
public virtual ApplicationUser User { get; set; }
[Key]
public int CreationLikeId { get; set; }
public virtual Creation ParentCreation { get; set; }
}
public class HairTag
{
[Key]
public int HairTagId { get; set; }
[Required]
public string HairTagTitle { get; set; }
[Required]
public string HairTagType { get; set; }
[Required]
public int HairTagOrder { get; set; }
}
***//CHECKBOXES
public class HairTagModel
{
[Key]
public int Value { get; set; }
public string Text { get; set; }
public bool IsChecked { get; set; }
}
public class HairTagList
{
private ApplicationDbContext creationdb = new ApplicationDbContext();
public HairTagList()
{
var HairTagList = creationdb.HairTags.ToList();
List<HairTagModel> obj = new List<HairTagModel>();
foreach (var tags in HairTagList)
{
obj.Add(new HairTagModel
{
Text = tags.HairTagTitle,
Value = tags.HairTagId,
IsChecked = false
});
}
this.CreationHairTags = obj;
}
public List<HairTagModel> CreationHairTags { get; set; }
//public List<HairTagModel> ListHairTags { get; set; }
}
public class CreationHairTagsModel
{
public Creation Creation { get; set; }
public List<HairTagModel> CreationHairTags { get; set; }
}
}***
My controller CreationController.cs
// GET: /Creation/CreationUpload
[Authorize]
public ActionResult CreationUpload()
{
CreationHairTagsModel creation = new CreationHairTagsModel();
return View(creation);
//return View();
}
// POST: /Creation/CreationUpload
// Afin de déjouer les attaques par sur-validation, activez les propriétés spécifiques que vous voulez lier. Pour
// plus de détails, voir http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[Authorize]
[ValidateAntiForgeryToken]
public ActionResult CreationUpload([Bind(Include = "CreationId,CreationSex,CreationTitle,CreationPhotoBis,CreationHairTags")] CreationHairTagsModel creation, IEnumerable<HttpPostedFileBase> files)
{
if (ModelState.IsValid)
{
// update each field manually
foreach (var file in files)
{
if (file != null)
{
if (file.ContentLength > 0)
{
....CODE UPLOAD HIDDEN....
//Avoid Script
var CreationTitletocheck = Regex.Replace(creation.Creation.CreationTitle, #"<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>", string.Empty);
CreationTitletocheck = Regex.Replace(CreationTitletocheck, #"(?></?\w+)(?>(?:[^>'""]+|'[^']*'|""[^""]*"")*)>", string.Empty);
creation.Creation.CreationTitle = CreationTitletocheck;
//Tags
StringBuilder sb = new StringBuilder();
foreach (var item in creation.CreationHairTags)
{
if (item.IsChecked)
{
sb.Append(item.Text + ",");
}
}
creation.Creation.Creationtag = sb.ToString();
creation.Creation.UserId = User.Identity.GetUserId();
db.Creations.Add(creation.Creation);
db.SaveChanges();
}
}
}
}
//UserId
return RedirectToAction("CreationList", "Creation", new { UserId = User.Identity.GetUserId() });
}
return View(creation);
}
My page of upload CreationUpload.cshtml
#model HairCollection3.Models.CreationHairTagsModel
#using Microsoft.AspNet.Identity
#{
ViewBag.Title = ViewRes.NamesCreation.CreationUploadTitle;
}
<div class="col-sm-12 col-md-12 chpagetop">
<h1>#ViewRes.Shared.PublishAPhoto</h1>
<hr />
#using (Html.BeginForm("CreationUpload", "Creation", FormMethod.Post, new { id = "CreationUpload", enctype = "multipart/form-data", onsubmit = "$('#creationloading').show(); $('#creationform').hide();" }))
{
#Html.AntiForgeryToken()
<div class="col-md-12" id="creationloading" style="display:none">
<div id="progress">
<p>#ViewRes.Shared.UploadPhotoProgress<strong>0%</strong></p>
<progress value="5" min="0" max="100"><span></span></progress>
</div>
</div>
<div class="col-md-12" id="creationform">
<div class="col-md-12">
#Html.ValidationMessageFor(m => m.Creation.CreationSex)
#Html.RadioButtonFor(m => m.Creation.CreationSex, "F", new { #checked = true }) #ViewRes.Shared.WomanHairstyle #Html.RadioButtonFor(m => m.Creation.CreationSex, "M") #ViewRes.Shared.ManHairstyle
</div>
<div class="col-md-12">
#Html.ValidationMessageFor(m => m.Creation.CreationTitle)
#Html.TextBoxFor(m => m.Creation.CreationTitle, new { #class = "inputplaceholderviolet wid100x100", placeholder = HttpUtility.HtmlDecode(Html.DisplayNameFor(m => m.Creation.CreationTitle).ToHtmlString()), onfocus = "this.placeholder = ''", onblur = "this.placeholder = '" + HttpUtility.HtmlDecode(Html.DisplayNameFor(m => m.Creation.CreationTitle).ToHtmlString()) + "'" })
</div>
<div class="col-md-12">
#for (int i = 0; i < Model.CreationHairTags.Count; i++)
{
#Html.CheckBoxFor(m => Model.CreationHairTags[i].IsChecked)
#Model.CreationHairTags[i].Text
#Html.HiddenFor(m => Model.CreationHairTags[i].Value)
#Html.HiddenFor(m => Model.CreationHairTags[i].Text)<br />
}
</div>
<div class="col-md-12" style="text-align: center">
<p style="display: inline-block">
<input type="file" accept="image/*" onchange="loadFile(event)" name="files" id="file1" translate="yes" data-val="true" data-val-required="A File is required." class="wid100x100" /><label for="file1"></label>
<img id="output" style="max-width:200px;"/>
</p>
</div>
<div class="col-sm-12 col-md-12 chpagetopdiv">
<button type="submit" title="#ViewRes.Shared.Publish"><span class="glyphicon glyphicon-share-alt"></span> #ViewRes.Shared.Publish</button>
</div>
</div>
}
</div>
What is wrong in my code please help and explain ?
Important: In C#, every collection must be initialized before being accessed
The error occurs when you are trying to access from the View to the collection CreationHairTags, which is not initialized. Replace your model to initialize collection in the class constructor:
public class CreationHairTagsModel
{
public Creation Creation { get; set; }
public List<HairTagModel> CreationHairTags { get; set; }
public CreationHairTagsModel()
{
CreationHairTags = new List<HairTagModel>();
}
}

Creating an MVC form using partial views each with complex models not binding to main model

I'm working on a form that has a main model being passed to the view. The model has sub-models within it, with partial views to render that content. The problem is that when I fill out the form, only those parameters on the main form get bound back to the model when the form is submitted.
I tried changing the Html.RenderPartial to a Html.EditorFor, and while it fixed my model binding problem, it removed all of my html formatting from the partial view.
Is there a way I can either bind my partial view elements to the main form model, or keep the html structure of my partial view using EditorFor?
Below is my code (I chopped out a bunch of stuff - especially from my main view - to try to simplify what I'm looking for).
This is my model:
public class ShipJobs
{
public String Job { get; set; }
public String Quote { get; set; }
public String PartName { get; set; }
public String Rev { get; set; }
public String Customer { get; set; }
public String CustomerName { get; set; }
public String TrackingNumber { get; set; }
public Int32 ShippedQuantity { get; set; }
public Boolean Certs { get; set; }
public Double ShippingCharges { get; set; }
public DateTime ShipDate { get; set; }
public String SelectedFreightTerms { get; set; }
public IEnumerable<SelectListItem> FreightTerms { get; set; }
public String SelectedContact { get; set; }
public IEnumerable<SelectListItem> Contacts { get; set; }
public String SelectedShipVia { get; set; }
public IEnumerable<SelectListItem> ShipVia { get; set; }
public Models.GreenFolders.Address Address { get; set; }
}
public class Address
{
public AddressType Type { get; set; }
public String ShipToId { get; set; }
public String ContactName { get; set; }
public String AddressName { get; set; }
public String Line1 { get; set; }
public String Line2 { get; set; }
public String City { get; set; }
public String State { get; set; }
public String Zip { get; set; }
public String Phone { get; set; }
public SelectList ShipToAttnDropDown { get; set; }
public IEnumerable<SelectListItem> ShipToDropDown { get; set; }
}
Controller:
public ActionResult ShipJobs(String Job, Models.Shipping.ShippingModel.ShipJobs Packlist, Models.GreenFolders.Address ShipAddress, String Submit = "")
{
var Model = new Models.Shipping.ShippingModel.ShipJobs();
if (Submit == "loadjob")
{
var shippingHelper = new BLL.Shipping.ShippingMethods(_company);
Model = shippingHelper.GetShipJobModel(Job);
Model.Address = shippingHelper.GetShipAddress(Job);
}
else if (Submit == "createpacklist")
{
}
ViewBag.Company = _company.ToString();
return View(Model);
}
Main View:
#model Models.Shipping.ShippingModel.ShipJobs
#{
ViewBag.Title = "ShipJobs";
String Company = ViewBag.Company.ToString();
}
#using (Html.BeginForm("ShipJobs", "Shipping", FormMethod.Post, new { Class = "form-horizontal" }))
{
<div class="row">
<div class="col-md-6">
<!-- Basic Form Elements Block -->
<div class="block">
<!-- Basic Form Elements Title -->
<div class="block-title">
<h2>Load <strong>Job</strong></h2>
</div>
<!-- END Form Elements Title -->
<!-- Basic Form Elements Content -->
#using (Html.BeginForm("ShipJobs", "Shipping", FormMethod.Post, new { Class = "form-horizontal form-bordered" }))
{
<div class="form-group">
<label class="col-md-3 control-label" for="example-text-input">Job Number</label>
<div class="col-md-9">
#Html.TextBoxFor(model => model.Job, new { id = "example-text-input", Name = "Job", Class = "form-control" })
</div>
</div>
<div class="form-group form-actions">
<div class="col-md-9 col-md-offset-3">
<button type="submit" class="btn btn-sm btn-primary" name="submit" value="loadjob"><i class="fa fa-angle-right"></i> Load Job Info</button>
<button type="reset" class="btn btn-sm btn-warning"><i class="fa fa-repeat"></i> Reset</button>
</div>
</div>
}
</div>
</div>
<div class="col-md-6">
#if (Model.Address != null && Model.Address != null)
{
#Html.EditorFor(model => model.Address)
//Html.RenderPartial("../Shared/_Address", Model.ShipInfo);
}
</div>
#Html.HiddenFor(model => model.Quote)
#Html.HiddenFor(model => Company)
</div>
}
Partial view:
#model Models.GreenFolders.Address
<!-- Block -->
<div class="block">
<div class="block-title">
#if(Model.Type == Models.GreenFolders.AddressType.Shipping)
{
<h2 style="float: right; margin-top: -9px; margin-right: -10px;">
<div class="dropdown shiptoddl">
<button class="btn btn-default dropdown-toggle" type="button" id="shiptoddl" data-toggle="dropdown" aria-expanded="true">
#Model.ShipToDropDown.Where(x => x.Selected).FirstOrDefault().Text
<span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu" aria-labelledby="dropdownMenu1">
#foreach (SelectListItem selectlistitem in Model.ShipToDropDown)
{
<li role="presentation"><a role="menuitem" tabindex="-1" href="#" data-value="#selectlistitem.Value" data-selected="#selectlistitem.Selected">#selectlistitem.Text</a></li>
}
</ul>
</div>
#*#Html.DropDownList("shiptoddl", (SelectList)Model.ShipToDropDown, new { #class = "shiptoddl", id = "shiptoddl" })*#
</h2>
}
<h4><strong>#Model.Type.ToString()</strong> Address</h4>
</div>
#{ Html.RenderPartial("../Shared/_AddressDetails", Model); }
</div>
<!-- END Block -->

Resources