ASP.NET MVC 3 Binding Unsuccessful - asp.net-mvc

I am having trouble making my ASP.NET MVC 3 View bind data back to a Model.
The typical objects such as string ContactName and string Title are being sent back successfully.
My public List<KeyValuePair<string, ListingTranslation>> ExpirimentToRemove object however isn't being sent back for some reason.
The following is contains code of the specific objects that aren't being binded successfully.
<div>
<ul class="nav nav-tabs">
#for (int i = 0; i < Model.ExpirimentToRemove.Count; i++)
{
<li class="#i == 0 ? 'active' : ''">#Model.Translations.Keys.ToList()[i]</li>
}
</ul>
<div class="tab-content" style="overflow: visible;">
#for (int i = 0; i < Model.ExpirimentToRemove.Count; i++)
{
<div class="tab-pane#i == 0 ? ' active' : ''" id="##Model.Translations.Keys.ToList()[i]">
#Html.TextBoxFor(m => Model.ExpirimentToRemove[i].Value.Title)
#Html.TextBoxFor(m => Model.ExpirimentToRemove[i].Value.FullDescription)
#Html.TextBoxFor(m => Model.ExpirimentToRemove[i].Value.PreviewDescription)
</div>
}
</div>

The trick for a list of items to be bound back is to have hidden fields.
Here is a great article explaining it in detail
Example:
<input type="hidden" name="products.Index" value="caliente" />
<input type="text" name="products[caliente].Name" value="Salsa" />
<input type="text" name="products[caliente].Price" value="1.23" />
The only other way is to manually manipulate the name attribute for the element that corresponds with the object path for the given item in List<T>.

Related

ASP.NET MVC - Check Box List for Link Table Values

Hoping someone can help me out, what I am trying to achieve a checkbox list (populated from a database table) which then inserts into a link table.
I'm not sure how best to achieve this, this is what I have so far which displays correctly, but I'm not sure how I can get this to save.
#using (Html.BeginForm("Create", "ReviewChecklistsController"))
{
foreach (var item in ViewBag.ChecklistId)
{
<div class="checkbox">
<label>
<input type="checkbox"
name="#item.Value"
value="#item.Value" /> #item.Text
</label>
</div>
}
<p></p>
<div class="form-group">
<input type="submit" class="btn btn-success" value="Save Checklist" />
</div>
}
Below is how I have set it up in the database, if you need any more information please let me know. I am using Entity Framework.
What I want is ReviewChecklist\ChecklistId to map to List_Checklist\ChecklistId and then State is just a boolean so if the checkbox is checked or not.
I've managed to get it working using the below. Is this okay, or is there a better way to do it?
#using (Html.BeginForm("Create", "ReviewChecklistsController"))
{
int i = 0;
foreach (var item in ViewBag.ChecklistId)
{
var nameStatus = "reviewChecklist[" + i + "].Status";
var nameReviewId = "reviewChecklist[" + i + "].ReviewId";
var nameChecklistId = "reviewChecklist[" + i + "].ChecklistId";
#Html.HiddenFor(model => model.ReviewId, new { Name = nameReviewId })
#Html.HiddenFor(model => model.ChecklistId, new { Name = nameChecklistId, Value = item.Value })
<p>
#Html.CheckBoxFor(model => model.Status, new { Name = nameStatus })
#item.Text
</p>
i++;
}
<p></p>
<div class="form-group">
<input type="submit" class="btn btn-success" value="Save Checklist" />
</div>
}

MVC foreach set item.ID to model.ID

I have a form that shows all the available hotel rooms, each room has a button that does a HttpPost if clicked, I have made a property in the BookingViewModel called 'RoomID'. I would like to assign the item.RoomID to Model.RoomID so I can use it in my controller to get the id from the selected room but i'm not sure how to achieve this.
ChooseRoom View
#foreach (var item in Model.AvailableRooms)
{
<li class="room-item clearfix">
<h5>#item.Name</h5>
<div class="room-list-left">
<img src="#item.Image" alt="" />
</div>
<div class="room-list-right">
<div class="room-meta">
<ul>
<li><span>Occupancy:</span> #item.Adults Adults #item.Childs Children</li>
#if (item.SmokingRoom)
{
<li><span>Smoking Allowed:</span> Yes</li>
}
else
{
<li><span>Smoking Allowed:</span> No</li>
}
</ul>
</div>
<div class="room-price">
<p class="price">From: <span>$#item.Price</span> / Night</p>
</div>
<div class="clearboth"></div>
#using (Html.BeginForm("chooseroom", "booking", FormMethod.Post))
{
<input class="button2" type="submit" value="Select Room" />
}
BookingController
[HttpPost]
public ActionResult ChooseRoom(BookingViewModel vm)
{
BookingViewModel bookingObj = GetBooking();
bookingObj.SelectedRoom = Repository.GetRoomByID(vm.RoomID);
return View("reservation", bookingObj);
}
Thank you for your time!
update your begin form as below
#using (Html.BeginForm("chooseroom", "booking", FormMethod.Post))
{
<input type="hidden" name="RoomId" value="#item.RoomID" />
<input class="button2" type="submit" value="Select Room" />
}
Just need to provide input tags having the same name as your ViewModel property.
You could add inputs in foreach loop , it should be inside form. Something like this <input name="Model.AvailableRooms[index].RoomID" value="Id Here"/>
Or if you want to select one Room you should use ajax and post id.
If I'm not wrong you form is in loop,so you could add hidden input with id
#Html.HiddenFor(c => c.AvailableRooms[index].RoomID)

MVC Razor, How to keep Model object between Actions

I'm trying to display a product stock list.
I would like to let the user an option to edit the quantity's and the ability to remove a product from this list. the problem is, the Model object disappear after the submit action. i would like to preserve it, in order to update the stock in DB later on.
Controllers:
public ActionResult EditProducts()
{
//! Pulling DATA from db using DbContext
ProductDAL proDAL = new ProductDAL();
List<Products> pl = proDAL.Products.ToList<Products>();
ProductModel productModel = new ProductModel();
productModel.oneProduct = new Products();
productModel.ProductsCollection = new List<Products>();
productModel.ProductsCollection = pl;
TempData["pM"] = productModel;
return View("EditProducts", TempData["pM"]);
}
public ActionResult SubmitProductsValues(ProductModel productModel)
{
//! Some farther work to do...
return View("EditProducts", TempData["pM"]);
}
My View:
#using (Html.BeginForm("SubmitProductsValues", "Admin", FormMethod.Post))
{
<div class="col-xs-12 hclearfix edit">
<div class="col-xs-2 eRow et"><b>Product SKU</b></div>
<div class="col-xs-2 eRow et"><b>Product Name</b></div>
<div class="col-xs-2 eRow et"><b>Product Price</b></div>
<div class="col-xs-2 eRow et"><b>Product Quantity</b></div>
<div class="col-xs-2 eRow et"><b>Product Picture</b></div>
<div class="col-xs-1 eRow et"><b>pId</b></div>
<div class="col-xs-1 eRow et"><b>Remove?</b></div>
#{ int i = 0; }
#foreach (Products obj in Model.ProductsCollection)
{
<div class="col-xs-2 eRow">#Html.Raw(obj.SKU)</div>
<div class="col-xs-2 eRow">#Html.Raw(obj.Name)</div>
<div class="col-xs-2 eRow">#Html.Raw(obj.Price)</div>
<div class="col-xs-2 eRow">#Html.EditorFor(m=>m.ProductsCollection[i].Quantity)</div>
<div class="col-xs-2 eRow">#Html.Raw(obj.PicURL)</div>
<div class="col-xs-1 eRow">#Html.Raw(obj.Id)</div>
<div class="col-xs-1 eRow">#Html.CheckBox("remove")</div>
i++;
}
<div class="col-xs-12 eRow">
<p class="left">
<input type="submit" id="btnSubmit" value="Save Changes" />
</p>
<p class="alert-danger right">
#Html.ValidationSummary()
</p>
</div>
</div>
BTW, only this raw: #Html.EditorFor keeps the values of the returned data.
but i would like to avoid using #Html.EditorFor for the other fields, while
keeping those fields data.
Thank you so much for your help (:
You are getting null because the other field values are not in the form fields. Model binding will map the data from your form fields ( with names matching to your view model property name). Currently you are displaying Name, Price etc in just a div, not an input field.
But since you do not want to update any other fields, you should not worry about getting other field value as null. What you need is the unique Id of your record and the Quantity field value which has the updated value from form.
Als you do not need TempData. You can pass your model to the View method.
public ActionResult EditProducts()
{
var proDAL = new ProductDAL();
List<Products> pl = proDAL.Products.ToList<Products>();
ProductModel productModel = new ProductModel();
productModel.ProductsCollection = new List<Products>();
productModel.ProductsCollection = pl;
return View("EditProducts",productModel);
}
And in your view, you need to create input fields with names which matches the property name so that model binding will work when you post the form.
#model ProductModel
#using (Html.BeginForm("SubmitProductsValues", "Admin", FormMethod.Post))
{
<h2>Items</h2>
int i = 0;
foreach(var p in Model.Products)
{
<div>#p.Name</div>
<input type="hidden" name="ProductsCollection[#i].Id" value="#p.Id" />
<input type="text" name="ProductsCollection[#i].Quantity" value="#p.Quantity" />
}
<input type="submit" value="Update" />
}
Now in your HttpPost, you will have the ProductsCollection available withe updated data from the form user submitted.
[HttpPost]
public ActionResult SubmitProductsValues(ProductModel model)
{
// loop through model.ProductsCollection
foreach(var p in Model.ProductsCollection)
{
var q=p.Quantity;
var id=q.Id;
// to do : update quantity of the record for the value in Id variable.
}
// to do : Save and redirect
}
<input type="hidden" name="ProductsCollection[#i].SKU" value="#p.SKU" />
<input type="hidden" name="ProductsCollection[#i].Name" value="#p.Name" />
<input type="hidden" name="ProductsCollection[#i].Price" value="#p.Price" />
<input type="hidden" name="ProductsCollection[#i].PicURL" value="#p.PicURL" />
<input type="hidden" name="ProductsCollection[#i].Id" value="#p.Id" />
Thanks to #Shyju (:

How can I export data in pdf using MVC?

This is My Index method by which I am getting the list of data in webgird.How can I write a method for exporting this list of data when I click on button?
public ActionResult Index(string eMailId)
{
var refEntry = _moneyReport.GetAll().Where(a => a.EmailId == eMailId).ToList();
var credittotal = _moneyReport.GetAll().Where(a => a.EmailId == eMailId && a.PromoValue < 0).Sum(a => a.PromoValue);
decimal TotalCredit = Convert.ToDecimal(credittotal * -1);
var debittotal = _moneyReport.GetAll().Where(a => a.EmailId == eMailId && a.PromoValue >0).Sum(a => a.PromoValue);
decimal TotalDebit = Convert.ToDecimal(debittotal);
ViewBag.TotDebit = TotalDebit;
ViewBag.TotCredit = TotalCredit;
if(TotalCredit>TotalDebit)
{
decimal FinalTotal = TotalCredit - TotalDebit;
ViewBag.Total = FinalTotal;
}
else
{
decimal FinalTotal = TotalDebit - TotalCredit;
ViewBag.Total = FinalTotal;
}
return View(refEntry);
}
This is my View page where I am entering an emailid,load and Export button`enter code here.
#using (Html.BeginForm())
{
<div class="container-fluid form-row">
<div class="col-md-12 no-padding">
<div class="col-md-3 no-padding">
<input type="text" name="eMailId" id="eMailId" />
<span class="highlight"></span>
<span class="bar"></span>
<label class="no-left">Enter Email Id <sup class="star">*</sup></label>
</div>
<div class="col-md-3">
<input type="text" id="gName" name="gName" readonly="readonly" />
<span class="highlight"></span>
<span class="bar"></span>
<label>Name</label>
</div>
<div class="col-md-3">
<input type="submit" id="btnLoad" class="btn btn-md pm-create" value="Load" />
<input type="submit" id="btnLoad" class="btn btn-md" value="Export To PDF" />
</div>
<input type="hidden" id="HdnEmail" value='#TempData["MailID"]' />
</div>
</div>
}
<div id="report-grid">
#{Html.RenderPartial("ImportMoneyReport", Model);}
</div>
ImPortMoneyReport is my partial page where i ve the webgrid.
To export model data to PDF you will have to use one of third party pdf export libraries such as few below. You will find sample examples on respective sites or google them. You will need to implement code to export pdf in and add that file/stream into Response.OutputStream by setting respective content type in ImportMoneyReport action. Also you will have to invoke ImportMoneyReport method on post/event you can not use Html.RenderPartial to export; otherwise you can put export code in Index action only.
PDF Sharp
iTextSharp
It you want something that's working and very easy to use. Take a look at https://github.com/andyhutch77/MvcRazorToPdf
Just read the documentation.
For sample code. Take a look at this.
https://github.com/andyhutch77/MvcRazorToPdf/tree/master/MvcRazorToPdfExample
If you encounter some issues go to their github page and click the Issues tab, maybe some of your questions are already resolved there.
P.S.
Some of the PDF libraries like Rotativa will require an executable program to run that will not work when your app is deployed to Azure because Azure doesn't support exe files (I guess for security purposes) else you'll create a webjob just for the exe file.

Design a Editor Template

Currently I have a editor template page which has the code:
#model Comics.Models.LocalComicCategoriesModel
#Html.LabelFor(x => x.Title, Model.Title)
#Html.CheckBoxFor(x => x.isChecked)
#Html.HiddenFor(x => x.Id)
Which I call from different pages with:
#Html.EditorFor(x => x.Categories)
When the template gets outputted, i just get a clunky html with no design to it like:
What I want is something like:
I can achieve this by doing:
#model IEnumerable<Comics.Models.LocalComicCategoriesModel>
<div id="checkbox-list">
#for (int iterator = 0; iterator < Model.Count(); iterator++)
{
if ((iterator % 6) == 0 || iterator == 0)
{
#Html.Raw("<div class='checkboxes_cont' style='float: left;'>");
}
string catTitle = Model.ElementAt(iterator).Title;
bool catChecked = Model.ElementAt(iterator).isChecked;
string catId = Model.ElementAt(iterator).Id.ToString();
<div class="itemtest" style="width: 100px;">
<input id="Categories_#iterator.ToString()__isChecked" name="Categories[#iterator.ToString()].isChecked" type="checkbox" value="#catChecked.ToString()" data-title="#catTitle" #if (catChecked) { Write("checked=checked"); }>
<label for="Categories_#iterator.ToString()__Title">#catTitle</label>
<input name="Categories[#iterator.ToString()].isChecked" type="hidden" value="false">
<input data-val="true" data-val-number="The field Id must be a number." id="Categories_#iterator.ToString()__Id" name="Categories[#iterator.ToString()].Id" type="hidden" value="#catId">
</div>
if ((iterator % 6) == 5 || iterator == Model.Count() - 1)
{
#Html.Raw("</div>")
}
}
</div>
However when I send data back to the controller, the value for the new checkbox dosent get sent back. I was wondering if it were possible to do it through the editor template.
The problem is that you're trying to solve the display with HTML, which is emphatically not the purpose of HTML; that's the domain of CSS. Apply style to the checkboxes in your stylesheet and let your HTML just be.

Resources