I am new to MVC and would like some help.
I have a view (below) which displays the products, next to each other. Till here everything is fine.
#foreach (var item in Model)
{
<a href="#Url.Action("showProductDetails", "Shared", new { ProductID = item.ProductID }, null)">
<div class='OutsideDiv' >
<table class='DivBorder'>
<tr >
<td class='title'>
#item.ProductName
</td>
</tr>
<tr >
<td class='imageBox'>
<img alt='' src="#item.ImageURL" />
</td>
</tr>
<tr>
<td class='title'>
#Html.Action("showAverageRating", "Rating" , new { ProductID = item.ProductID } ) *************
</td>
</tr>
<tr>
<td class='desc'>
#item.Description
</td>
</tr>
<tr>
<td class='price'>
€ #item.Price
</td>
</tr>
</table>
</div>
<script type='text/javascript'> $('.DivBorder').mouseover(function () { $(this).css('border-color', '#0953cb'); $(this).css('background-color', '#eaeaea'); }); $('.DivBorder').mouseout(function () { $(this).css('border-color', '#bdbdbd'); $(this).css('background-color', '#f6f6f6'); });</script>
</a>
}
In the line marked with '****' above I am calling another view (showAverageRating) which for now is just displaying 5 rating stars with the first 3 starts selected.
<input class="star " name="adv1" type="radio" />
<input class="star " name="adv1" type="radio" />
<input checked="checked" class="star " name="adv1" type="radio" />
<input class="star " name="adv1" type="radio" />
<input class="star " name="adv1" type="radio" />
The problem is that on the second item, when the rating stars view (above partial view) is called again, the stars are displayed next to the stars of the first product, picture below.
I think I have to use something else rather than Html.Action?
EDIT : showAverageRating Code
public ActionResult showAverageRating(int ProductID)
{
decimal averageRating = new RatingsService.RatingsClient().getAverageRating(ProductID);
ViewData["averageRating"] = averageRating;
return PartialView();
}
The problem was that the name of the stars where identical, so I included the productID with their name, like below.
showAverageRating partial view
#{decimal averageRating = ViewBag.averageRating;}
#{int productID = ViewBag.productID;}
<div id="averageRating" >
<input class="star" name="star+#productID" type="radio" />
<input class="star " name="star+#productID" type="radio" />
<input checked="checked" class="star " name="star+#productID" type="radio" />
<input class="star " name="star+#productID" type="radio" />
<input class="star " name="star+#productID" type="radio" />
</div>
Related
Html code
<label class="control-label">Contact Person</label>
<input class="form-control" type="text" placeholder="Enter Contact name" data-bind="value: ContactPerson" data-validate='{"required":"true"}'><br />
<label class="control-label">ContactNo</label>
<input class="form-control" type="tel" data-bind="value: ContactNo" placeholder="ContactNo" data-validate='{"required":"true"}'><br />
<label class="control-label">E-Mail</label>
<input class="form-control" type="email" data-bind="value: Email" placeholder="Email" data-validate='{"required":"true","email":"true"}'><br />
<table class="table table-hover table-bordered" id="listTable">
<thead>
<tr>
<th>ContactPerson</th>
<th>ContactNo</th>
<th>Email</th>
<th></th>
</tr>
</thead>
<tbody data-bind="template:{name: 'Process-list',
foreach: rootViewModel.BodyContent.ProcessList }">
</tbody>
</table>
when I click on add button the data in the three text box should bind to grid ,
and when i click on delete button of row in grid it should disappear for this i need viewmodel.
Thanks
Here's a quick view model that does the requirements. I selected ContactNo as the primary key since they're supposed to be unique. You can use ids if needed instead. It would also be a good idea to run your validations before add method is called.
var viewModel = function(){
var self = this;
self.ContactPerson = ko.observable();
self.ContactNo = ko.observable();
self.Email = ko.observable();
self.ProcessList = ko.observableArray();
self.add = function(){
self.ProcessList.push({
ContactPerson: self.ContactPerson(),
ContactNo: self.ContactNo(),
Email: self.Email(),
});
self.ContactPerson('');
self.ContactNo('');
self.Email('');
};
self.delete = function(data, event){
self.ProcessList.remove(function(listObject){
return listObject.ContactNo === data.ContactNo;
});
};
};
ko.applyBindings(new viewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<label class="control-label">Contact Person</label>
<input class="form-control" type="text" placeholder="Enter Contact name" data-bind="value: ContactPerson" data-validate='{"required":"true"}'><br />
<label class="control-label">ContactNo</label>
<input class="form-control" type="tel" data-bind="value: ContactNo" placeholder="ContactNo" data-validate='{"required":"true"}'><br />
<label class="control-label">E-Mail</label>
<input class="form-control" type="email" data-bind="value: Email" placeholder="Email" data-validate='{"required":"true","email":"true"}'><br />
<button data-bind="click: add">Add Data</button>
<table class="table table-hover table-bordered" id="listTable">
<thead>
<tr>
<th>ContactPerson</th>
<th>ContactNo</th>
<th>Email</th>
<th></th>
</tr>
</thead>
<tbody data-bind="template:{name: 'Process-list',
foreach: ProcessList }">
</tbody>
</tbody>
</table>
<script type="text/html" id="Process-list">
<tr>
<td data-bind="text: ContactPerson"></td>
<td data-bind="text: ContactNo"></td>
<td data-bind="text: Email"></td>
<td><button data-bind="click: $root.delete">Delete</button></td>
</tr>
</script>
How to save image path or name to database and copy the image in a folder. I have searched many pages on the internet but no luck. Please can anyone show my how to create the controller?
My View
<form action="Create" method="post">
<table>
<tr>
<td>
<input type="date" name="InquirDate" id="InquirDate" placeholder="Date" />
</td>
<td>
<input type="text" id="signby" name="signby" placeholder="signby" />
</td>
<td>
<input type="text" id="description" name="description" placeholder="Description" />
</td>
<td>
<input type="text" id="parentInqNo" name="parentInqNo" placeholder="Parent Inquiry number">
</td>
<td>
<select id="status" name="status">
<option>Draft</option>
<option>Published</option>
</select>
</td>
<td>
<input type="text" id="number" name="number" placeholder="number" />
</td>
</tr>
<tr>
<td>
<input type="text" name="subject" id="subject" placeholder="Subject" />
</td>
<td>
<input type="text" id="empid" name="empid" placeholder="empid" />
</td>
<td>
<input type="file" name="Attachment" id="Attachment" />
</td>
<td>
<input type="text" name="InqiurURL" id="InqiurURL" placeholder="InqiurURL" />
</td>
<td>
<input type="text" name="EnterDate" id="EnterDate" placeholder="EnterDate" />
</td>
</tr>
</table>
<input type="submit" value="Save">
</form>
Try following this code in your controller
public ActionResult Save(FormCollection fc, HttpPostedFileBase Attachment)//Instead of Attachment better to use "file"
{
if (Attachment!= null)
{
Database1Entities db = new Database1Entities();
string ImageName = System.IO.Path.GetFileName(Attachment.FileName);
string physicalPath =Server.MapPath("~/images/"+ ImageName);
// save image in folder
Attachment.SaveAs(physicalPath);
//save new record in database
tblA newRecord = new tblA();
newRecord.empid= fc.empid;
newRecord.subject= fc.subject;
//....Add all field which need to save in db
newRecord.Attachment= ImageName;
db.tblA.Add(newRecord);
db.SaveChanges();
}
return View();
}
As shown in my post here the GET action method Test(..) works fine when using foreach loop in the corresponding Test.chtml view but the POST action method Test(...) returns null. But, as mentioned by many users, the foreach is not reliable for POST method. So, I decided to use the for loop as shown below. But that returned unexpected results in the view since, according to this post, in a foreachloop type casting is done automatically but in for loop you have to type cast the objects Model[i].BlogID etc to a proper class object type.
So, I decided to type cast the objects Model[i].BlogID etc to a BlogsWithRelatedPostsViewModel class object type as shown in the second version of Test.cshml view below; and this time the Test.cshtml view is displayng the correct records. But although the submit button in the view is sending a a valid model (ModelState.IsValid is true) the Model.Count is 0 that results in no update to database. Why Model.Count is 0 and how to correct it? As you can see below the html page source of the view is showing the name attributes of the tags matching the property values in the View Model.
Note: For complete code, please see this OP. I'm using ASP.NET Core with EF Core and Tag Helpers.
Test.cshtml view with for loop - without type casting the loop objects:
#model IList<ASP_Core_Blogs.Models.BlogPostViewModels.BlogsWithRelatedPostsViewModel>
#using ASP_Core_Blogs.Models.BlogPostViewModels
#{ ViewData["Title"] = "Index"; }
<div class="row">
<div class="col-md-12">
<form asp-controller="Blogs" asp-action="Test" asp-route-returnurl="#ViewData["ReturnUrl"]" method="post">
#{
IEnumerable<SelectListItem> yearsList = (IEnumerable<SelectListItem>)ViewBag.YearsList;
var currentlySelectedIndex = 0; // Currently selected index (usually will come from model)
}
<strong>Select a Post Year</strong>
<h6>Choose a year and a URL to begin:</h6>
<label>Year:</label><select asp-for="#currentlySelectedIndex" asp-items="yearsList"></select><input type="submit" class="btn btn-default" name="GO" value="GO" />
<table class="table">
<thead>
<tr>
<th></th>
<th></th>
<th>Url</th>
<th>Title</th>
<th>Content</th>
</tr>
</thead>
<tbody>
#for (int i=0; i< Model.Count(); i++)
{
<tr>
<td><input type="hidden" asp-for="#Model[i].BlogID" /></td>
<td><input type="hidden" asp-for="#Model[i]).PostID" /></td>
<td>
<input type="text" asp-for="#Model[i].Url" style="border:0;" readonly />
</td>
<td>
<input asp-for="#Model[i].Title" />
</td>
<td>
<input asp-for="#Model[i].Content" />
</td>
</tr>
}
</tbody>
</table>
<button type="submit" class="btn btn-default">Save</button>
</form>
</div>
</div>
Test.cshtml view with for loop objects being casted as BlogsWithRelatedPostsViewModel class objects:
#model IList<ASP_Core_Blogs.Models.BlogPostViewModels.BlogsWithRelatedPostsViewModel>
#using ASP_Core_Blogs.Models.BlogPostViewModels
#{ ViewData["Title"] = "Index"; }
<div class="row">
<div class="col-md-12">
<form asp-controller="Blogs" asp-action="Test" asp-route-returnurl="#ViewData["ReturnUrl"]" method="post">
#{
IEnumerable<SelectListItem> yearsList = (IEnumerable<SelectListItem>)ViewBag.YearsList;
var currentlySelectedIndex = 0; // Currently selected index (usually will come from model)
}
<strong>Select a Post Year</strong>
<h6>Choose a year and a URL to begin:</h6>
<label>Year:</label><select asp-for="#currentlySelectedIndex" asp-items="yearsList"></select><input type="submit" class="btn btn-default" name="GO" value="GO" />
<table class="table">
<thead>
<tr>
<th></th>
<th></th>
<th>Url</th>
<th>Title</th>
<th>Content</th>
</tr>
</thead>
<tbody>
#for (int i=0; i< Model.Count(); i++)
{
<tr>
<td><input type="hidden" asp-for="((BlogsWithRelatedPostsViewModel)#Model[i]).BlogID" /></td>
<td><input type="hidden" asp-for="((BlogsWithRelatedPostsViewModel)#Model[i]).PostID" /></td>
<td>
<input type="text" asp-for="((BlogsWithRelatedPostsViewModel)#Model[i]).Url" style="border:0;" readonly />
</td>
<td>
<input asp-for="((BlogsWithRelatedPostsViewModel)#Model[i]).Title" />
</td>
<td>
<input asp-for="((BlogsWithRelatedPostsViewModel)#Model[i]).Content" />
</td>
</tr>
}
</tbody>
</table>
<button type="submit" class="btn btn-default">Save</button>
</form>
</div>
</div>
A Portion of html generated by View after Submit:
<tr>
<td><input type="hidden" data-val="true" data-val-required="The BlogID field is required." id="BlogID" name="BlogID" value="1" /></td>
<td><input type="hidden" data-val="true" data-val-required="The PostID field is required." id="PostID" name="PostID" value="1" /></td>
<td>
<input type="text" style="border:0;" readonly id="Url" name="Url" value="blog1#test.com" />
</td>
<td>
<input type="text" id="Title" name="Title" value="Title1" />
</td>
<td>
<input type="text" id="Content" name="Content" value="Content1" />
</td>
</tr>
I want to get filtered items size related to the product
this is Method json that returns by Id
public ActionResult getProductSize(int prodID)
{
YAT.CMS.Shared.DAL.JAGUAREntities dbContext = new YAT.CMS.Shared.DAL.JAGUAREntities();
var getsize = (from a in dbContext.ProductSizes
where a.ProductID == prodID
select a.Description).ToList();
//var json_string = "{ Size: \"\" }";
return Json(getsize, JsonRequestBehavior.AllowGet);
}
and this is my View the section that hold category cart Description
#for (int i = 0; i < Model.Count; i++)
{
<tr class="odd">
<td class="imageCnt">
<a href="#Url.Action("ProductDetails", "Product", new { ID = #Model[i].Id })">
<img class="bp-image" alt="#Model[i].EN_Name" src="#Url.Content("~/Admin/Admin_Cataloge/Product/" + #Model[i].Photo)" />
</a>
<input type="hidden" name="[#i].ProductID" value="#Model[i].Id" />
</td>
<td class="titleCnt">
#Model[i].EN_Name
</td>
<td class="priceCnt">#Model[i].Price<span class="currency"> </span>
<input id="#("Price" + i.ToString())" value="#Model[i].Price" type="hidden" />
</td>
<td class="quantityCnt">
<span class="basketQuantityCnt">
<input data-val="true" data-val-number="The field Quantity must be a number." data-val-required="The Quantity field is required." id="#("Quantity" + i)" name="[#i].Quantity" onkeypress="return restrictCharacters(this, event);" type="text" value="1"/>
<a class="deleteBtn" href="#" onclick="deleteBasketString(this,#Model[i].Id);"></a>
<a class="updateBtn" href="#" onclick="Calculate()"></a>
<a class="bq-plus" onclick="IncreaseQuantity(this);Calculate();"></a>
<a class="bq-minus" onclick="DecreaseQuantity(this);Calculate();"></a>
</span>
</td>
<td class="prodsize">
<select id="selectNumber">
<option>Choose a number</option>
//Here where i want to add Filtered Size for item
</select>
</td>
<td class="subTotalCnt" id="#("total" + i)">#Model[i].Price<span class="currency"> </span>
</td>
</tr>
total += Model[i].Price;
}
how to do this in the Commented in view where I want to do this?
I have a dynamic forms with checkbox/radio-button lists & matrices:
Following code renders checkbox list:
#foreach (var sq in Model.SubQuestions)
{
<label>
<input type="hidden" name="answerResult.index" value="#sq.Id" />
<input type="checkbox" name="answerResult[#sq.Id].SubQuestionId" value="#sq.Id" />
#sq.Label.Name
</label>
}
radio-button list:
<input type="hidden" name="answerResult.index" value="#Model.Id" />
#foreach (var sq in Model.SubQuestions)
{
<label>
<input type="radio" name="answerResult[#Model.Id].SubQuestionId" value="#sq.Id" />
#sq.Label.Name
</label>
}
My POST-action in controller:
[HttpPost]
public ActionResult PassageSurvey(int surveyId, int surveyPageIndex, IList<AnswerResult> answerResult)
where IList<AnswerResult> is an auto-bound collection from my form. I get only items that were checked/selected. Everything is going well.
Now I need to get the same collection from checkbox/radio-button matrices.
Radio-button matrix:
<table width="100%">
<tr>
<th></th>
#foreach (var av in Model.AnswerVariants)
{
<th style="text-align: center;">
<label>#av.Label.Name</label>
</th>
}
</tr>
#foreach (var sq in Model.SubQuestions)
{
<tr>
<td>
<label>#sq.Label.Name</label>
<input type="hidden" name="answerResult.index" value="#sq.Id" />
<input type="hidden" name="answerResult[#sq.Id].SubQuestionId" value="#sq.Id" />
</td>
#foreach (var av in Model.AnswerVariants)
{
<td align="center">
<input type="radio" name="answerResult[#sq.Id].AnswerVariantId" value="#av.Id" />
</td>
}
</tr>
}
</table>
Checkbox matrix:
<table width="100%">
<tr>
<th></th>
#foreach (var av in Model.AnswerVariants)
{
<th style="text-align: center;">
<label>#av.Label.Name</label>
</th>
}
</tr>
#foreach (var sq in Model.SubQuestions)
{
<tr>
<td>
<label>#sq.Label.Name</label>
</td>
#foreach (var av in Model.AnswerVariants)
{
<td align="center">
<input type="hidden" name="answerResult.index" value="#sq.Id" />
<input type="hidden" name="answerResult[#sq.Id].AnswerVariantId" value="#sq.Id" />
<input type="checkbox" name="answerResult[#sq.Id].SubQuestionId" value="#sq.Id" />
</td>
}
</tr>
}
</table>
POST-action in controller always the same.
Now from radio-button matrix (in current sample 3x3) IList<AnswerResult> gets always 3 items, depending on items that were selected in rows and columns.
But from Checkbox matrix (3x3) IList<AnswerResult> gets always all 9 items (regardless items were checked, hidden-inputs always have values)
But I want to get only items, that were checked. How could I change my checkbox-matrix template to solve this problem?
Finally I decided to handle this problem in my post-action instead. Removing items (checkboxes) that were not selected, and have nulls in answerResult[##].SubQuestionId fields.