can't pass data to my controller from views - c#

I'm trying to pass 5 optional values to my controller
public class ActivityManagementTwoFiltersModel
{
public string timeFilter { get; set; } = "Last 30 days";
public int numberOfItemsToReturn { get; set; } = 25;
public DateTime? dateStart { get; set; } = null;
public DateTime? dateEnd { get; set; } = null;
public Guid? districtId { get; set; } = null;
}
my controller is like this
public async Task<ActionResult> ActivityManagementTwo( ActivityManagementTwoFiltersModel filters)
my view:
#{using (Html.BeginForm("ActivityManagementTwo", "CallCenter", FormMethod.Get, new { id = "ActivityTwoForm" }))
{
<div class="row ">
<div class="col-md-12" style="float:right;">
<div class="dateWrapper">#{Html.RenderPartial("_DateFilter"); }</div>
</div>
</div>
<div class="row" style="margin-top: 10px; margin-bottom: 8px;">
<div class="col-md-3 ActivityManagementTwoHeader" style="font-size:12px; font-weight: bold">
Displaying Results #Model.Count() of #Model.Count()
</div>
<div class="col-md-3">
Items per page:
#Html.DropDownList("numberOfItemsToReturn", new List<SelectListItem> {
new SelectListItem { Value = "25", Text= "25"},
new SelectListItem { Value = "50", Text= "50"},
new SelectListItem { Value = "100", Text= "100"},
})
</div>
</div>
}
}
I want to hit my controller from the main view or partial view whenever one of the dropdown menu's is changed. I tried a JS function but it didn't submit the values
document.getElementById("numberOfItemsToReturn").addEventListener("change", function () {
document.getElementById("ActivityTwoForm").submit();
})
didn't work. How can I pass the controller the parameters from the drop down menu's on change?
edit: Here's my partial view. The partial View fields are being sent , it's only the numberOfItemsToReturn that are not
<table>
<tr>
<td style="text-align:right; vertical-align: top; width: 160px">
Time filter:
</td>
<td style="display:inline-block; width:150px" >
<input id="radio1" name="radioToggle" type="radio"> Recent
<select id="timeFilter" name="timeFilter" >
<option value="Last 30 days">at least 18</option>
</select>
<br />
<input id="radio2" name="radioToggle" class="radioTimeFilter" type="radio"> Date Range
<div id="dateContent" class="radio-content" style="display:none;">
<input id="txtDateOneFilter" type="text" style="width: 70px;" placeholder="Start Date" name="dateStart"/> to
<input id="txtDateTwoFilter" type="text" style="width: 70px;" placeholder="End Date" name="dateEnd" />
</div>
<br />
</td>
</tr>
</table>

Add [HttpPost] to the action
[HttpPost]
public async Task<ActionResult> ActivityManagementTwo( ActivityManagementTwoFiltersModel filters)
then fix your form
#{using (Html.BeginForm("ActivityManagementTwo", "CallCenter", FormMethod.Post))
Add Submit button to the form to test it
<input type="submit" value="Send" />

#Html.DropDownList(m => m.numberOfItemsToReturn, new List<SelectListItem> {
new SelectListItem { Value = "25", Text= "25"},
new SelectListItem { Value = "50", Text= "50"},

Related

Why does Controller 'Get' Edit method getting called twice in ASP.NET Core 6 MVC?

I have problem in edit view. When I debug my code, after Id is passed from ShowCategory view to EditPostGroup method in controller, it works correctly, but after page loads, Id zero is sent to the Edit method in controller and throws an error
Object reference not set to an instance of an object
This is my code: this method is in the PostRepository and get postGroup with Id from database :
public PostGroupViewModel GetPostGroupById(int postGroupId)
{
var postGroup = _context.PostGroups.Find(postGroupId);
PostGroupViewModel postGroupViewModel = new PostGroupViewModel()
{
GroupId = postGroup.GroupId,
GroupTitle = postGroup.GroupTitle,
GroupImageName = postGroup.GroupImageName,
IsDelete = postGroup.IsDelete,
ParentId = postGroup.ParentId
};
return postGroupViewModel;
}
These are Get and Post edit method in CategoryController:
[HttpGet]
public IActionResult EditPostGroup(int id)
{
var groups = _postService.GetGroupForManagePost();
ViewData["Groups"] = new SelectList(groups, "Value", "Text");
var postGroupViewModel = _postService.GetPostGroupById(id);
return View(postGroupViewModel);
}
[HttpPost]
public IActionResult EditPostGroup(PostGroup postGroup, IFormFile imgPostGroupUp)
{
if (!ModelState.IsValid)
return View("EditPostGroup");
_postService.UpdatePostGroup(postGroup, imgPostGroupUp);
return RedirectToAction("ShowCategory", "Category");
}
This is 'ShowCategory' View, It sends PostGroupId to Edit action method:
#{
ViewData["Title"] = "Category List";
}
<div class="row">
<div class="col-lg-12">
<h4 style="color:darkblue;" >Category List</h4>
</div>
<!-- /.col-lg-12 -->
</div>
<br />
<div class="row">
<div class="col-lg-12">
<div class="panel panel-default">
<div class="panel-body">
<br />
<div class="col-md-12" style="margin: 10px 0;">
<a asp-controller="Category" asp-action="CreateCategory" asp-area="Admin" class="btn btn-outline btn-success">Create Category</a>
</div>
<br />
<br />
<br />
<table class="table table-striped table-bordered table-hover dataTable no-footer text-center" id="dataTables-example" aria-describedby="dataTables-example_info">
<thead class="table-success black-ribon">
<tr>
<th>Title</th>
<th>Parent Category</th>
<th>Image</th>
<th>Operations</th>
</tr>
</thead>
<tbody>
#foreach (var item in #ViewBag.CategoryList)
{
<tr>
<td>
#item.GroupTitle
</td>
<td>
#item.ParentId
</td>
<td>
<img class="thumbnail" style="width:40px;height:40px;" src="/img/postGroup/#item.GroupTitle/#item.GroupImageName" alt="">
</td>
<td>
<a href="/Admin/Category/EditPostGroup/#item.GroupId" class="btn btn-primary btn-md">
Edit
</a>
</td>
</tr>
}
</tbody>
</table>
</div>
<!-- /.panel-body -->
</div>
<!-- /.panel -->
</div>
<!-- /.col-lg-12 -->
</div>
This is the EditPostGroupView:
#model DataLayer.Models.ViewModels.PostGroup.PostGroupViewModel
#{
ViewData["Title"] = "Post Edit";
//Layout = "~/Areas/Admin/Views/Shared/_AdminLayout.cshtml";
}
<div class="row">
<form method="post" asp-action="EditPostGroup" enctype="multipart/form-data">
#* <input type="hidden" asp-for="GroupId" />*#
#*<input type="hidden" asp-for="Post.PostImageName"/>*#
<div class="col-md-8">
<h2>Category List</h2>
<hr/>
<div class="form-group">
<label>Title</label>
<input type="text" asp-for="GroupTitle" class="form-control">
<span asp-validation-for="GroupTitle"></span>
</div>
<div class="form-group">
<label>ParentId</label>
<select class="form-control" asp-for="ParentId" asp-items="#(ViewData["Groups"] as SelectList)">
<option value="">-- please select --</option>
</select>
<span asp-validation-for="ParentId"></span>
</div>
</div>
<div class="col-md-4">
<p></p>
<img id="imgPost" class="thumbnail" src="img/postGroup/#Model.GroupTitle/#Model.GroupImageName"/>
<div class="form-group">
<label>Select Image</label>
<input type="file" name="imgPostGroupUp" id="imgPostGroupUp">
</div>
</div>
<input type="submit" value="Edit" class="btn btn-success"/>
</form>
</div>
#section scripts
{
<script>
function readURL(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
$('#imgPost').attr('src', e.target.result);
}
reader.readAsDataURL(input.files[0]);
}
}
$("#imgPostUp").change(function () {
readURL(this);
});
</script>
}
This is the Routing in Program.cs:
app.MapControllerRoute(
name: "MyArea",
pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}");
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
This is PostGroup Model:
public class PostGroup
{
[Key]
public int GroupId { get; set; }
//public int? SubGroupId { get; set; }
public string GroupTitle { get; set; }
[MaxLength(50)]
public string? GroupImageName { get; set; }
public bool IsDelete { get; set; }
[Display(Name = "Category")]
public int? ParentId { get; set; }
[ForeignKey("ParentId")]
public List<PostGroup>? PostGroups { get; set; }
[InverseProperty("PostGroup")]
//[NotMapped]
public List<Post>? Posts { get; set; }
}
This is postGroupViewModel:
public class PostGroupViewModel
{
public int GroupId { get; set; }
public string GroupTitle { get; set; }
[MaxLength(50)]
public string? GroupImageName { get; set; }
public bool IsDelete { get; set; }
public int? ParentId { get; set; }
}
What is the problem?
Could it be a problem with the Program.cs and middleware?
I changed EditPostGroup(PostGroup postGroup, IFormFile imgPostGroupUp) method to
EditPostGroup(PostGroupViewModel postGroupViewModel, IFormFile imgPostGroupUp),but there is still a problem.
You can use a query string instead of passing the id in .net core:
[HttpGet]
public async Task<IActionResult> Edit()
{
string id = HttpContext.Request.Query["id"].ToString();
var model = await _service.FindAsync(int.Parse(id));
return View(model);
}
in razor view:
<a href="/service/edit?id=#item.ServiceId">
Also, using # in the src of a file in razor view causes this problem. remove it or give it a value.
<img id="img-master" class="thumbnail" src="#" />
to
<img id="img-master" class="thumbnail" src="/images/#Model.ImageEdit" />

How to pull table record in asp.net mvc 5 using jquery?

I have modal form, but i am struggling to pull the table record from the database once a user first check radio button(EmailAddress) and puts a correct email from the Textbox, as soon click Next button it must prompt following columns Name, EmailAddress, LoginID, SSID and Institution. Below is my logic and need some help to put it back with data.
<pre> public class eNtsaRegPeopleLists
{
public string Name { get; set; }
[Key]
public int LoginID { get; set; }
public string Name {get;set;}
public string SISID { get; set; }
public string EmailAddress {get;set;}
public string Role { get; set; } // ignore this one from the View
public DateTime LastActivity { get; set; } // ignore this one from the View
public decimal TotalActivity { get; set; } // ignore this one from the View
public string Institution { get; set; }
}
<div class="form-group row">
<div class="col-sm-4">
<input type="radio" id="EmailAddress" name="choose" />
<label for="EmailAddress" class="col-form-label">EmailAddress</label>
</div>
<div class="col-sm-3">
<input type="radio" id="LoginID" name="choose" />
<label for="LoginID" class="col-form-label">LoginID</label>
</div>
<div class="col-sm-3">
<input type="radio" id="SIS_ID" name="choose"/>
<label for="SIS_ID" class="col-form-label">SIS_ID</label>
</div>
<div class="col-sm-12">
#Html.TextAreaFor(m => m.eNtsaAdmin.eNtsaTextAreaDisc, new { #class = "form-control", style = "font-size: medium; font-weight: bold; width:450px", id= "eNtsaTextAreaDisc" })
</div>
<hr />
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModalCenter" id="btnNext">
Next
</button>
</div>
#foreach(var data in Model.regPeopleLists)
{
}
<div class="modal-body">
<table class="table table-bordered">
<thead>
<tr>
<th>Name</th>
<th>EmailAddress</th>
<th>LoginID</th>
<th>SISID</th>
</tr>
</thead>
</table>
</div>
<script type="text/javascript">
$(document).ready(function () {
$(document).ready(function () {
// Fire when radio button clicked
$("#LoginID, #SIS_ID").bind("change", function () {
checkdata();
});
// Fire when we enter anything in the textbox
$("#eNtsaTextAreaDisc").bind("input", function () {
checkdata();
});
});
//here we check both radio button clicked and textbox filled with some information
function checkdata() {
if (($("#LoginID").prop("checked") || $("#SIS_ID").prop("checked")) && $("#eNtsaTextAreaDisc").val().length > 0) {
$("#btnNext").removeAttr("disabled");
}
else {
$("#btnNext").attr("disabled", "disabled");
}
}
</script>

asp.net core how can i post category and subcategory from table row

Here is my Category.cs,
public class Category
{
public int Id { get; set; }
[Required, StringLength(100),Display(Name="Category Name")]
public string Name { get; set; }
[Display(Name="Category Description")]
public string Description { get; set; }
public bool IsActive { get; set; }
public IList<Style> Style { get; set; }
public IList<SubCategory> SubCategories { get; set; }
}
public class SubCategory
{
public int Id { get; set; }
public string Value { get; set; }
}
public class IndexModel : PageModel
{
[Microsoft.AspNetCore.Mvc.BindProperty]
public Category ViewModel { get; set; }
public void OnGet()
{
// You can fill your ViewModel property here.
}
public void OnPost()
{
// You can read your posted ViewModel property here.
}
}
And DbContext.cs
public DbSet<Category> Categories { get; set; }
public DbSet<SubCategory> SubCategory { get; set; }
And AddCategory.cshtml
#model UretimPerformans.Entity.Admin.IndexModel
#{
ViewData["Title"] = Localizer["addca"];
Layout = "~/Views/Shared/_AdminLayout.cshtml";
}
#section Scripts{
<link href="~/dist/plugins/bootstrap-switch/css/bootstrap3/bootstrap-switch.min.css" rel="stylesheet" />
<script src="~/js/jquery-3.5.1.js"></script>
<style>
td, tr {
text-align: center;
vertical-align: middle;
}
</style>
}
#section Scripts2{
<script src="~/dist/plugins/bootstrap-switch/js/bootstrap-switch.js"></script>
<script>
$("#btnSearch").click(function () {
var t = null;
t = $("#tab_logic tbody tr").get().map(function (tr) {
return $(tr).find("input").get().map(function (input) {
return input.value
})
})
$("#regTitle").html(t);
});
</script>
<script>
$(document).ready(function () {
var i = 1;
$("#add_row").click(function () {
$('#addr' + i).html("<td>" + (i + 1) + "</td><td><input name='name" + i + "' required type='text' placeholder='SubCategory-" + i + "' class='form-control input-md' /> </td><td><input name='mail" + i + "' type='checkbox' placeholder='IsActive' class='form-control'></td>");
$('#tab_logic').append('<tr id="addr' + (i + 1) + '"></tr>');
i++;
});
$("#delete_row").click(function () {
if (i > 1) {
$("#addr" + (i - 1)).html('');
i--;
}
});
});
$(function () {
$("input[data-bootstrap-switch]").each(function () {
$(this).bootstrapSwitch('state', $(this).prop('checked'));
});
})
</script>
}
<section class="content-header">
<div class="container-fluid">
<div class="row mb-2">
<div class="col-sm-6">
<h1>#Localizer["addca"]</h1>
</div>
<div class="col-sm-6">
<ol class="breadcrumb float-sm-right">
<li class="breadcrumb-item"><a asp-action="Index" asp-controller="Home">#Localizer["anasayfa"]</a></li>
<li class="breadcrumb-item"><a asp-action="Index" asp-controller="Catalog">#Localizer["cat"]</a></li>
<li class="breadcrumb-item"><a asp-action="Categories" asp-controller="Catalog">#Localizer["ca"]</a></li>
<li class="breadcrumb-item active">#Localizer["addca"]</li>
</ol>
</div>
</div>
</div>
</section>
<section class="content">
<div class="card">
<div class="card-body">
<form asp-action="AddCategories" asp-controller="Catalog" method="post">
<div class="form-group row">
<span class="col-md-3">#Localizer["name"]</span>
<div class="col-md-9">
<input type="text" class="form-control" asp-for="ViewModel.Name" required />
</div>
</div>
<div class="form-group row">
<span class="col-md-3">#Localizer["desc"]</span>
<div class="col-md-9">
<textarea type="text" id="regTitle" class="form-control" asp-for="ViewModel.Description" required></textarea>
</div>
</div>
<div class="form-group row">
<span class="col-md-3">#Localizer["aktif"]</span>
<div class="col-md-9">
<input type="checkbox" asp-for="ViewModel.IsActive" checked data-bootstrap-switch data-off-color="danger" data-on-color="success">
</div>
</div>
<fieldset class="module">
<h4>#Localizer["alt"]</h4>
<button id="btnSearch">Click</button>
<a id="add_row" class="btn btn-default pull-left">Add Row</a>
<a id='delete_row' class="pull-right btn btn-default">Delete Row</a>
<hr />
<div class="row clearfix">
<div class="col-md-12 column">
<table class="table table-bordered table-hover" id="tab_logic">
<thead>
<tr>
<th class="text-center">
#
</th>
<th class="text-center">
SubCategoryName
</th>
<th class="text-center">
IsActive
</th>
</tr>
</thead>
<tbody>
<tr id='addr0'>
<td>1</td>
<td>
<input asp-for="ViewModel.SubCategories[1].Value" />
#Model.ViewModel.SubCategories[1].Value
</td>
</tr>
<tr id='addr0'>
<td>
1
</td>
<td>
<input type="text" name='name0' placeholder='Name' class="form-control" />
</td>
<td>
<input type="checkbox" name='mail0' placeholder='Mail' class="form-control" />
</td>
</tr>
<tr id='addr1'></tr>
</tbody>
</table>
</div>
</div>
</fieldset>
<div class="card-footer">
<button type="submit" class="btn btn-primary">#Localizer["kaydet"]</button>
</div>
</form>
</div>
</div>
</section>
And CategoryController,
[HttpGet]
public IActionResult AddCategories()
{
return View();
}
[HttpPost]
public IActionResult AddCategories(Category entity)
{
if (ModelState.IsValid)
{
categoryRepository.AddCategory(entity);
TempData["success"] = "Başarıyla kaydedildi.";
return RedirectToAction("Categories");
}
else
{
return View(entity);
}
}
My codes are as above. What I want to do is add subcategories from the table at the bottom of the category when adding a category. but I could not set up the model. and I could not write the post method and reading method in indexmodel.
Please can you help me?
Thank you
Kind Regards
I don’t understand the meaning of name0 and name1..., neither Category nor SubCategory have this attribute. In addition, if you add SubCategoryName by adding a row in the table, this SubCategory class does not have the attribute 'IsActive'.
If you only want to add SubCategories through the rows of the table, you can follow this example.
Here I simulate some data.
public class IndexModel : PageModel
{
[Microsoft.AspNetCore.Mvc.BindProperty]
public Category ViewModel { get; set; }
public void OnGet()
{
ViewModel = new Category
{
Id = 1,
Description = "desc",
IsActive = false,
Name="name",
SubCategories=new List<SubCategory>
{
new SubCategory
{
Id=10,Value="val"
},
new SubCategory
{
Id=20,Value="val2"
},
new SubCategory
{
Id=30,Value="val3"
},
}
};
// You can fill your ViewModel property here.
}
}
I find discorrect asp-controller here.
Because the name in the form starts with 'ViewModel', the mapped model should be modified like this.
[HttpPost]
public IActionResult AddCategories(Category ViewModel)
{
//...
return Json(ViewModel);
}
Then, the result is as follows.

Foreach loop returning database search results to a view in cshtml

Cannot implicitly convert type
CourseSearchResultMode to IEnumerable. An explicit conversion exists (are
you missing a cast?)
Controller:
namespace RedPandaCourses.Controllers
{
public class SearchController : Controller
{
[HttpGet]
public ActionResult CourseSearchView()
{
var courses = new CourseSearchResultModel();
return View(courses);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult CourseSearchView(CourseSearchResultModel vm)
{
var courses = new CourseSearchResultModel();
return View(courses);
}
2 Models:
namespace RedPandaCourses.Models
{
public class CourseSearchModel
{
public CourseSearchModel() { }
public string courseName { get; set; }
public int courseNumber { get; set; }
public string courseInstructor { get; set; }
public List<CourseSearchResultModel> results { get; set; }
}
}
and
namespace RedPandaCourses.Models
{
public class CourseSearchResultModel
{
public CourseSearchResultModel() { }
public decimal courseID { get; set; }
public string courseName { get; set; }
public string courseNumber { get; set; }
public string courseInstructorFirstName { get; set; }
public string courseInstructorLastName { get; set; }
public string courseInstructor { get; set; }
public string courseSchedule { get; set; }
}
}
It will send text box text to the database, search it from a select class, and return the results to the table using a foreach loop, however the foreach loop throws the error above.
View:
#Model RedPandaCourses.Models.CourseSearchResultModel;
#using RedPandaCourses.Models;
#{
ViewBag.Title = "CourseSearchView";
Layout = "~/Views/Shared/_AdminLayout.cshtml";
}
<div class="container-fluid no-main-border">
<div class="row-fluid main-bg">
<div class="span12">
<h2 class="labelHide"> </h2>
<div class="row-fluid">
<div class="negMargin">
<div class="span9 inner-container">
<div class="streamlined-subhead">
<h1>Search Courses</h1>
</div>
#using (Html.BeginForm("CourseSearchView", "Search"))
{
var model = new CourseSearchModel();
<div id="the_id" class="question">
<div class="control-group" id="the_id_control-group">
<fieldset>
<div id="the_id_1_control-group" class="control-group">
<label class="control-label" for="courseName">Course Name: </label>
<div id="the_id_1_controls" class="controls">
#Html.TextBoxFor(m => model.courseName)
</div>
</div>
<div id="the_id_2_control-group" class="control-group">
<label class="control-label" for="courseNumber">Course Number: </label>
<div id="the_id_2_controls" class="controls">
#Html.TextBoxFor(m => model.courseNumber)
</div>
</div>
<div id="the_id_3_control-group" class="control-group">
<label class="control-label" for="instructor">Instructor: </label>
<div id="the_id_3_controls" class="controls">
#Html.TextBoxFor(m => model.courseInstructor)
</div>
</div>
<div class="previous-next-bar">
<button type="submit" class="btn btn-primary" id="courseSearch" onclick="location.href='#Url.Action("CourseSearchView","Search")'">Search</button>
</div>
</fieldset>
</div>
</div>
}
<div>
<h2>Search Results</h2>
<table id="example" class="table table-bordered table-striped table-hover dataTable width80">
<thead class="tableHeader" role="rowgroup">
<tr role="row">
<th class="sorting" role="columnheader">Course Title</th>
<th class="sorting" role="columnheader">Course Number</th>
<th class="sorting" role="columnheader">Instructor</th>
<th class="sorting" role="columnheader">Schedule</th>
</tr>
</thead>
<tbody>
#if (Model == null)
{
<tr>
<td colspan="4">no results</td>
</tr>
} else {
foreach (var item in Model)
{
Html.AntiForgeryToken();
<tr class="clickableRow" onclick="location.href='#Url.Action("InstructorCourseDetailView", "Instructor")'">
<td>#Html.Encode(item.courseName)</td>
<td>#Html.Encode(item.courseNumber)</td>
<td>#Html.Encode(item.courseInstructor)</td>
<td>#Html.Encode(item.courseSchedule)</td>
</tr>
}
}
<tr>
<td colspan="4">
<button class="btn btn-default" onclick="location.href='#Url.Action("AdminAddCourseView","Admin")'">Add Course</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<div class="row-fluid">
<div class="span12">
<div class="previous-next-bar">
<button type="submit" class="btn btn-default" onclick="location.href='#Url.Action("AdminHome","Admin")'">Return</button>
</div>
</div>
</div>
</div>
</div>
</div>
I've looked everywhere including a bunch of questions on this site and cannot find anything that has helped me in this situation. I'm new to coding, this is the training application I'm doing for my new job and any help would be appreciated!
To start with, the form should sending a CourseSearchModel not a CourseSearchResultModel.
Second, in the action handling the post, you should query the database and put the result in the results property of the search model you received as an argument. Here is how to do it :
[HttpPost]
[ValidateAntiForgeryToken]
//Change the type of the object bound from the from
public ActionResult CourseSearchView(CourseSearchModel vm)
{
//Query the db and put the outcome in the results prop of the vm
vm.results = QueryTheDb();
//return the vm to the view
return View(vm);
}
Third, you give that object to the View method in the return line.
Fourth, change this
#Model RedPandaCourses.Models.CourseSearchResultModel;
with this
#Model RedPandaCourses.Models.CourseSearchModel;
in your view.

How to insert data within a table?

I need to insert a data from a table which has a foreach loop inside. I used to work with webforms so I'm newbie to mvc. I always encountered this scenario in webforms using gridview control and just implement the findcontrol command and it works fine. But in mvc, I could hardly get the solutions how to do it. I already search online but can't find any articles that fits my needs for this type of issue. So far, what I've got is if I insert a data from a first row of the table it will insert the record but if I insert them from the second, third, and so fourth, it will no longer insert the records into my database table. How do I make this perfectly be working?
Heres my model,view and controller to help you resolve the issue. Thanks...
Model
public class CommentModel
{
public int Id { get; set; }
[Required(ErrorMessage="Don't miss to put your name.")]
public string name { get; set; }
[Required(ErrorMessage = "Don't leave your comments empty.")]
public string comment { get; set;}
}
public class ReplyModel
{
public int idrep { get; set; }
public string namerep { get; set; }
public string reply { get; set; }
}
public class CreateViewModel
{
public CommentModel CreateComment { get; set; } // this line is optional
public ReplyModel CreateReply { get; set; }
public List<CommentModel> Comments { get; set; }
public List<ReplyModel> Replies { get; set; }
}
Repository:
public class ReplyRepository
{
private ProfileDataContext3 Reprepository;
public ReplyRepository()
{
Reprepository = new ProfileDataContext3();
}
public IEnumerable<ReplyModel> GetAllComments()
{
List<ReplyModel> profiles = new List<ReplyModel>();
var prof = from profile in Reprepository.RepTabs
orderby profile.Id descending
select profile;
var user = prof.ToList();
foreach (var item in user)
{
profiles.Add(new ReplyModel()
{
idrep = item.Id,
namerep = item.Name,
reply = item.Replies
});
}
return profiles;
}
//declaring methods for inserting records
public void InsertReply(ReplyModel profile)
{
var details = new RepTab()
{
Id=profile.idrep,
Name = profile.namerep,
Replies = profile.reply
};
Reprepository.RepTabs.Add(details);
Reprepository.SaveChanges();
}
}
Controller
public ActionResult PostComment()
{
var vModel = new CreateViewModel();
vModel.Comments = comrepository.GetAllComments().ToList();
vModel.Replies = replyrepository.GetAllComments().ToList();
return View(vModel);
}
[HttpPost]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult PostComment(CommentModel com,string butname, ReplyModel rep)
{
switch(butname)
{
case "Post Comments":
if (ModelState.IsValid)
{
comrepository.InsertComment(com); //this is to insert the records
}
//this is to display the records inserted
var vModel = new CreateViewModel();
vModel.Comments = comrepository.GetAllComments().ToList();
vModel.Replies = replyrepository.GetAllComments().ToList();
return View(vModel);
case "Post Reply":
if (ModelState.IsValid)
{
replyrepository.InsertReply(rep); //this is to insert the records
}
//this is to display the records inserted
var vModel2 = new CreateViewModel();
vModel2.Comments = comrepository.GetAllComments().ToList();
vModel2.Replies = replyrepository.GetAllComments().ToList();
return View(vModel2);
default:
return null;
}
}
View
#model MyFirstMVCApp.Models.CreateViewModel
#{
ViewBag.Title = "PostComment";
}
<h2>Post Comment</h2>
<br />
#using (Html.BeginForm("PostComment", "Profile", FormMethod.Post, new { }))
{
#Html.ValidationSummary("Unable to Post Comment. Please correct the errors and try again...")
<fieldset>
<legend>CommentModel</legend>
<div class="editor-label">
<label for="name">Name</label>
</div>
<div class="editor-field">
<input type="text" id="name" name="name" />
<span class="field-validation-valid" data-valmsg-for="name" data-valmsg-replace="true"></span>
</div>
<div class="editor-label">
<label for="comment">Post your Comment here:</label>
</div>
<div class="editor-field">
<textarea id="comment" name="comment" style="width:500px;height:100px;resize:none" ></textarea>
<span class="field-validation-valid" data-valmsg-for="comment" data-valmsg-replace="true"></span>
</div>
<p>
<input type="submit" value="Post Comments" name="butname" />
#Html.ActionLink("See Comments", "DisplayComment")
</p>
<br />
</fieldset>
}
<br />
<h2>Comments</h2>
<br />
#using (Html.BeginForm("PostComment", "Profile", FormMethod.Post, new { }))
{
<table>
#foreach (var item in Model.Comments)
{
<tr>
<td>
<div class="editor-field" style="display:none;margin-bottom:10px;margin-top:10px">
#Html.TextBoxFor(m => m.CreateComment.Id)
</div>
<div style="font-weight:bold;"> #Html.DisplayFor(modelItem => item.name) </div>
<p style ="margin-top:0px;margin-bottom:0px; border-radius: 4px 4px 4px 4px; max-width :500px; min-height :5px; display :block; background-color: #CCCCFF"> #Html.DisplayFor(modelItem => item.comment) </p>
<p style="margin-top:2px;margin-bottom:0px"> <input type="button" id="like" name="like" value="Like" style="color:blue;border:0px;background-color:inherit;cursor:pointer" /> <input type="button" id="Reply" name="Reply" value="Replie(s)" style="color:blue;border:0px;background-color:inherit;cursor:pointer" /></p>
<div id="divrep" style="position:relative;left:50px; overflow:auto;margin-top:0px">
<table>
#foreach (var item2 in Model.Replies)
{
<tr>
<td>
<p style ="margin-top:0px;margin-bottom:0px; border-radius: 4px 4px 4px 4px; max-width :445px; min-height :5px; display :block; background-color: #CCCCFF;">#Html.DisplayFor(modelItem => item2.reply) </p>
<br />
</td>
</tr>
}
</table>
</div>
<input type="text" id="idrep" name="idrep" value="#Html.DisplayFor(modelItem=>item.Id)" />
<span class="field-validation-valid" data-valmsg-for="idrep" data-valmsg-replace="true"></span>
<br />
<input type="text" id="namerep" name="namerep" />
<span class="field-validation-valid" data-valmsg-for="namerep" data-valmsg-replace="true"></span>
<br />
<textarea id="reply" name="reply" style="width:500px;height:100px;resize:none" ></textarea>
<span class="field-validation-valid" data-valmsg-for="reply" data-valmsg-replace="true"></span>
<br />
<input type="submit" value="Post Reply" name="butname" />
</td>
</tr>
}
</table>
}
<br />
<br />
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section scripts
{
<script type ="text/jscript" src="JQuery/jquery-1.4.3.min.js">
</script>
<script type="text/javascript">
$('body').keypress(function(e) {
if (e.which == 13) {
$("input[value='Post Comments']").trigger('click');
}
});
</script>
}
The problem is the naming of your controls, you have multiple controls with the same name and the DefaultModelBinder will only bind the first one (i.e the first row) and ignore the rest. I suggest a different approach using jquery to post new comments and avoid having to refresh the page each time.
View
...
#using (Html.BeginForm()) {
<div>
#Html.LabelFor(m => m.CreateComment.Name)
#Html.TextBoxFor(m => m.CreateComment.Name)
#Html.ValidationMessageFor(m => m.CreateComment.Name)
// repeat for CreateComment.Comment property
<input type="submit" id="post-comment" value="Submit Comment" />
</div>
}
...
Script
$('form').submit(function(e) {
e.preventDefault(); // prevent submission
}
$('#post-comment').click(function() {
// get values for postback
var inputs = $(this).closest('div').find('input');
var name = inputs.first().val();
var comment = inputs.last().val();
var url = '#Url.Action("PostComment", "Profile")';
$.post(url, { Name: name, Comment: comment }, function(data) {
if(data) {
inputs.val(''); // clear existing inputs
// create a new element for the comment and add to the DOM, for example
var para = $('div></div>).text(comment).appendTo(something);
} else {
// display an error message
}
}
}
and add a similar script for posting replies, except use a class name not id for the button so there are no duplicate id's
Controller
[HttpPost]
public ActionResult PostComment(CommentModel model)
{
// save the comment and if successful
return Json(true);
else
return null;
}
For posting back replies, in your foreach loop, add a hidden input for the respective comment ID and include that in the data to post back to a separate action
[HttpPost]
public ActionResult PostReply(ReplyModel model)
{
...

Categories