I am having the error message:I can`t figure out what is wrong. Can someone help me please. Thanks.
Stack Trace:
[NotSupportedException: Collection is
read-only.]
System.SZArrayHelper.Clear() +56
System.Web.Mvc.CollectionHelpers.ReplaceCollectionImpl(ICollection`1
collection, IEnumerable newContents)
+125
ExecuteStep(IExecutionStep step,
Boolean& completedSynchronously) +184
My code is:
Model:
namespace TestArrays.Models
{
public class Person
{
public CategoriesRow[] Categories { get; set; }
public Person()
{
Categories = new CategoriesRow[1];
Categories[0] = new CategoriesRow();
Categories[0].Name = "Bug";
Categories[0].ID = "0";
}
}
public class CategoriesRow
{
public String Name { get; set; }
public String ID { get; set; }
}
}
Controller
public ActionResult Create()
{
return View(new Person());
}
//
// POST: /Person/Create
[HttpPost]
public ActionResult Create(Person person)
{
try
{
// TODO: Add insert logic here
return RedirectToAction("Index");
}
catch
{
return View();
}
}
Views
<form id="Form" action="<%=Url.Action("Create",new{Action="Create"}) %>" method="post" enctype="multipart/form-data">
<div id="categoriessection" >
<h3>Categories</h3>
<ul class= "list" id="categoryList">
<%if (Model.Categories!=null) {%>
<%int count = 0; %>
<%foreach (var category in Model.Categories)
{%>
<%if (!String.IsNullOrEmpty(category.Name))
{%>
<li><input type="hidden" name="Categories.Index" value="<%=count%>" />
<input type="text" value="<%=category.Name%>" name="Categories[<%=count%>].Name" style="width:280px"/>
<input type="hidden" value="<%=category.ID%>" name="Categories[<%=count++%>].ID" style="width:280px"/>
<input type="button" value = "Delete"/>
</li>
<%}
%>
<%} %>
<%} %>
<li> <input type="hidden" name="Categories.Index" value="value0" />
<input type="text" value="" name="Categories[value0].Name" style="width:280px"/>
<input type="hidden" value="" name="Categories[value0].ID" style="width:280px"/>
<input type="button" value= "Add" />
</li>
</ul>
</div>
<div>
<input type ="submit" value="Save" id="save" />
</div>
</form>
I usually use lists instead of vectors in models:
public List<CategoriesRow> Categories { get; set; }
Related
I encountered the problem when I was creating a Create page. Which lead me to an error message which says:
Error Message:
Im not entirely sure if my model name is correct.
Below are my following codes:
Songs Controller:
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Data.SqlClient;
using System.Data;
using System.Data.SqlClient;
using System;
using Garcia___MVC.Models;
namespace Garcia___MVC.Controllers
{
public class SongsController : Controller
{
private const string ConnectionString =
#"*";
// GET: SongsController
[HttpGet]
public ActionResult Index()
{
DataTable dtbSongs = new DataTable();
using(SqlConnection sqlCon = new SqlConnection(ConnectionString))
{
sqlCon.Open();
SqlDataAdapter sqlDa = new SqlDataAdapter("SELECT * FROM Songs",sqlCon);
sqlDa.Fill(dtbSongs);
}
return View(dtbSongs);
}
// GET: SongsController/Create
[HttpGet]
public ActionResult Create(object model)
{
return View(model);
}
// POST: SongsController/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(IFormCollection collection)
{
try
{
return RedirectToAction(nameof(Index));
}
catch
{
return View();
}
}
// GET: SongsController/Edit/5
public ActionResult Edit(int id)
{
return View();
}
// POST: SongsController/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(int id, IFormCollection collection)
{
try
{
return RedirectToAction(nameof(Index));
}
catch
{
return View();
}
}
// GET: SongsController/Delete/5
public ActionResult Delete(int id)
{
return View();
}
// POST: SongsController/Delete/5
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Delete(int id, IFormCollection collection)
{
try
{
return RedirectToAction(nameof(Index));
}
catch
{
return View();
}
}
}
}
Create Page that can't be accessed:
#model Garcia___MVC.Models.SongsModel
#{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>SongsModel</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="SongID" class="control-label"></label>
<input asp-for="SongID" class="form-control" />
<span asp-validation-for="SongID" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="SongTitle" class="control-label"></label>
<input asp-for="SongTitle" class="form-control" />
<span asp-validation-for="SongTitle" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Artists" class="control-label"></label>
<input asp-for="Artists" class="form-control" />
<span asp-validation-for="Artists" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Album" class="control-label"></label>
<input asp-for="Album" class="form-control" />
<span asp-validation-for="Album" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
SongsModel.cs
using System;
namespace Garcia___MVC.Models
{
public class SongsModel
{
public int SongID { get; set; }
public string SongTitle { get; set; }
public string Artists { get; set; }
public string Album { get; set; }
}
}
Would appreciate any advice or tips on how I can go about this. Will be very much appreciated.
I was expecting a page which you can create the Song title, Artists, Album, and Song ID.
The return type of the action in the songsController must be SongsModel.
The type you specify at the top of the view page determines the return type.
I'm sorry for my bad english.
I'm trying to build one view that includes all (Create, Edit, Delete, and Index) in one View which is Index.
The problem is with Editing. Always returns null to the controller as shown in the gif.
I have Model and ViewModel as follows.
The Model BootstrapCategory
public class BootstrapCategory
{
[Key]
public Guid Id { get; set; }
[MaxLength(20)]
[Required]
public string Category { get; set; }
}
The ViewModel VMBPCategoris
public class VMBPCategoris
{
public List<BootstrapCategory> bootstrapCategories { get; set; }
public BootstrapCategory bootstrapCategory { get; set; }
}
The View
Note: Edit not by the usual button in the table it instead by another
button as shown in the gif
#model VMBPCategoris
#foreach (var item in Model.bootstrapCategories)
{
<tr>
<td>
<form asp-action="Edit" method="post">
<input type="hidden" asp-for="#item.Id" />
<div class="#item.Id d-none">
<div class="input-group">
<input id="btnGroupEdit" type="submit" value="Save" class="input-group-text btn btn-primary" />
<input asp-for="#item.Category" class="form-control" aria-label="Input group example" aria-describedby="btnGroupEdit">
</div>
<span asp-validation-for="#item.Category" class="text-danger"></span>
</div>
</form>
<div class="#item.Id">
#Html.DisplayFor(modelItem => item.Category)
</div>
</td>
<td>
Edit |
<a asp-action="Details" asp-route-id="#item.Id">Details</a> |
<a asp-action="Delete" asp-route-id="#item.Id">Delete</a>
</td>
</tr>
}
The Controller
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit([Bind("Id,Category")] BootstrapCategory bootstrapCategory)
{
_context.Update(bootstrapCategory);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
//return View(vMBPCategoris);
}
The view model class VMBPCategoris needs to have its members properties assigned to instances in a constructor:
public class VMBPCategoris
{
public List<BootstrapCategory> bootstrapCategories { get; set; }
public BootstrapCategory bootstrapCategory { get; set; }
public VMBPCategoris()
{
bootstrapCategories = new List<BootstrapCategory>();
bootstrapCategory = new BootstrapCategory();
}
}
You can give a name to your input tag.Change your form like below.
<form asp-action="Edit" method="post">
<input type="hidden" asp-for="#item.Id" name="Id"/>
<div class="#item.Id d-none">
<div class="input-group">
<input id="btnGroupEdit" type="submit" value="Save" class="input-group-text btn btn-primary" />
<input asp-for="#item.Category" name="Category" class="form-control" aria-label="Input group example" aria-describedby="btnGroupEdit">
</div>
<span asp-validation-for="#item.Category" class="text-danger"></span>
</div>
</form>
I made an easy solution by changing a little bit with the ViewModel and using the value attribute to get value from a model and using asp-for to set a value to another model.
It's all clarified in that Stackoverflow post
I have a viewmodel:
public class ProductInShopsCheckboxViewModel
{
public ProductInShop? ProductInShop { get; set; }
public IEnumerable<ProductInShop>? Checkboxes { get; set; }
}
view(that works):
#model WebApp.ViewModels.ProductInShopsCheckboxViewModel
#if (Model?.Checkboxes != null) {
<h4>#Model.Checkboxes!.ElementAt(0).Shop!.ShopName</h4>
<p></p>
<form asp-action="Create">
#for (var i = 0; i < Model.Checkboxes!.Count(); i++) {
<input type="checkbox" asp-for="Checkboxes.ElementAt(i).IsSelected">#Model.Checkboxes.ElementAt(i).Product?.ProductName
<p></p> }
<div class="form-group">
<input type="submit" value="Send email" class="btn btn-primary"/>
</div>
</form> }
<p></p>
<a asp-action="Index">Back to Shops</a>
and controller:
[HttpPost]
public IActionResult Create(ProductInShopsCheckboxViewModel vm)
{
//TODO: check which vm.Checkboxes items are selected
//Send those items to mail(code ready)
}
However I get back viewmodel with empty list and I cannot figure out what I'm doing wrong. I appreciate any advice.
This is my HomeWithIndentityController
namespace MVC.CRUDDynamicFormTest.Controllers
{
public class HomeWithIndentityController : Controller
{
// GET: HomeWithIndentity
public ActionResult WithIndex()
{
return View();
}
public ActionResult GetData()
{
using (DynamicCRUDDatabase2Entities db = new DynamicCRUDDatabase2Entities())
{
List<DynamicCRUDTable2> dynamicCRUDTable2s = db.DynamicCRUDTable2.ToList<DynamicCRUDTable2>();
return Json(new { data = dynamicCRUDTable2s }, JsonRequestBehavior.AllowGet);
}
}
[HttpGet]
public ActionResult Add(int id = 0)
{
return View(new DynamicCRUDTable2());
}
[HttpPost]
public ActionResult Add(DynamicCRUDTable2 obj)
{
using (DynamicCRUDDatabase2Entities db = new DynamicCRUDDatabase2Entities())
{
db.DynamicCRUDTable2.Add(obj);
db.SaveChanges();
return Json(new { succces = true, message = "saved Successfully" }, JsonRequestBehavior.AllowGet);
//return RedirectToAction("Index", "Home");
}
}
}
}
this is my entity model class
public partial class DynamicCRUDTable2
{
public int Id { get; set; }
public string FirstName { get; set; }
}
This my View
<form action="~/HomeWithIndentity/Add" method="POST" onsubmit="return Submitform(this)">
<input data-val="true" id="Id" name="Id" type="hidden" />
<label>First Name</label>
<input type="text" name="FirstName[]" class="form-control" />
<input type="text" name="FirstName[]" class="form-control" />
<br />
<br />
<div>
<input type="submit" value="Submit" class="btn btn-success" />
<input type="reset" value="Reset" class="btn btn-danger" />
<a class="btn btn-danger" href="~/Home/Index">Cancel</a>
</div>
</form>
In the above view i want to add the firstname input field values to the Database dynamicallly.but it does not working can you let me know why?What errors i have done.
does anyone know how to do that?
I'm trying to have a button on my form page that takes me back to the previous view that requires a parameter, I'm passing a ViewModel into the view with the assigned value I'm using. If the button is un-commented the button works fine but the forms post sends a NullReferenceException, and if the button is commented the form works exactly as I want.
The button that breaks the form
<button type="button" onclick="location.href='#Url.Action("Assignments","Session", new { Model.CourseName })'">Go Back</button>
The Controller Code
public IActionResult CreateAssignment(string courseName)
{
CreateAssignmentModel assignmentModel = new CreateAssignmentModel();
assignmentModel.CourseName = courseName;
return View(assignmentModel);
}
[HttpPost]
public IActionResult CreateAssignment(CreateAssignmentModel assignment)
{
if (ModelState.IsValid)
{
ModelState.Clear();
return View(assignment.CourseName);
}
else
{
return View(assignment.CourseName);
}
}
public IActionResult Assignments(string courseName)
{
var assignments = storedProcedure.getAssignments(User.Identity.Name, courseName);
var AssignmentsView = new AssignmentsViewModel{CourseName = courseName};
foreach (var Assignment in assignments.ToList())
{
AssignmentsView.Assignments.Add(Assignment);
}
return View(AssignmentsView);
}
The Model Code
public class CreateAssignmentModel
{
public string UserName { get; set; }
public string CourseName { get; set; }
[Required]
public string AssignmentName { get; set; }
[Required]
public string AssignmentDescription { get; set; }
[Required]
public int TotalPoints { get; set; }
[Required]
public DateTime DueDate { get; set; }
}
The Form with Button
<button type="button" onclick="location.href='#Url.Action("Assignments","Session", new { Model.CourseName })'">Go Back</button>
<div class="row">
<div class="col-md-4">
<form asp-route-returnUrl="#ViewData["ReturnUrl"]" method="post">
<h4>Create an Assignment</h4>
<hr />
<div class="form-group">
<label asp-for="AssignmentName" class="control-label">Assignment Name</label>
<input asp-for="AssignmentName" class="form-control" placeholder="Assignment Name" />
<span asp-validation-for="AssignmentName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="AssignmentDescription" class=" control-label">Assignment Description</label>
<input asp-for="AssignmentDescription" class="form-control" placeholder="Assignment Description" />
<span asp-validation-for="AssignmentDescription" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="TotalPoints" class=" control-label">Total Points</label>
<input asp-for="TotalPoints" class="form-control" placeholder="Points" />
<span asp-validation-for="TotalPoints" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="DueDate" class=" control-label">Due Date</label>
<input asp-for="DueDate" class="form-control" placeholder="Due Date" />
<span asp-validation-for="DueDate" class="text-danger"></span>
</div>
<br />
<button type="submit" class="btn btn-primary">Create</button>
</form>
</div>
</div>
Sorry for the lack of brevity, I've looked at NullReferenceException solutions for my problem but none have worked.