I have a viewmodel class like this:
public class ViewModel
{
public string VendorService { get; set; }
public List<ResponseView> responseList { get; set; }
}
Controller has get and post edit actions:
public ActionResult Edit(int? id)
{
List<ResponseView> resp = getResponseView(id); //get the list of ResponseView objects.
ViewModel view = new ViewModel();
view.responseList = resp;
view.VendorService = "Car Manufacturer";
return View(view);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(ViewModel view)
{
if (ModelState.IsValid)
{
List<ResponseView> respList = new List<ResponseView>();
respList = view.responseList;
foreach(ResponseView resp in respList)
{
Debug.WriteLine(resp.Question);
}
return RedirectToAction("editConfirm");
}
return View("Index");
}
Edit.cshtml
#model Tools.Models.ViewModel
#{
List<Tools.Models.ResponseView> respList= Model.responseList as List<Tools.Models.ResponseView;
}
#foreach (var item in respList)
{
<div class="col-md-5">
#Html.EditorFor(model => item.Response, "" } })
#Html.ValidationMessageFor(model => item.Response, "", "" })
</div>
}
I am able to display the view and all the data in the View Model as required. But I am getting a null pointer reference when I try to retrieve the response in my post action, on foreach line below.
List<ResponseView> respList = new List<ResponseView>();
respList = view.responseList;
foreach(ResponseView resp in respList)
{
Debug.WriteLine(resp.Response);
}
You have to use for instead foreach . Please try this,
#for (int i = 0; i < Model.responseList.Count; ++i) {
<div>
#Html.EditorFor(model => Model.responseList[i].Response, "")
</div>
Related
I tried to call method from controller with Ajax, but it never enters the method, i'm import unobtrusive and validate in Bundle, and always refresh all the page. I'm first time in C# i use vb.net, maybe it's a basical error, but i search a lot and try diferent ways and nothing. thanks for ur time and i hope someone can help me
Update: i have a form inside Master page and that generate the problem D:
View
#model PlanificacionOperacional.Models.FiltroView
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#section Styles
{
#Styles.Render("https://cdn.datatables.net/1.11.3/css/jquery.dataTables.min.css")
#Styles.Render("https://cdn.jsdelivr.net/npm/bootstrap-select#1.13.14/dist/css/bootstrap-select.min.css")
}
<div class="card-header header-elements-inline" style="padding-top:0;"><h4 class="card-title">Muestreos</h4></div>
<fieldset>
#using (Ajax.BeginForm("Filtrar", "Muestreo",
new AjaxOptions
{
UpdateTargetId = "tabless",
HttpMethod = "POST"
}))
{
<div class="form-group">
#Html.DropDownListFor(model => model.predio, new SelectList(ViewBag.formularios, "id", "nombre"), new { #class = "selectpicker", data_live_search = "true", title = "Predio" })
#Html.DropDownListFor(model => model.zona, new SelectList(ViewBag.zonas, "id", "nombre"), new { #class = "selectpicker", data_live_search = "true", title = "Zona" })
#Html.DropDownListFor(model => model.area, new SelectList(ViewBag.areas, "id", "nombre"), new { #class = "selectpicker", data_live_search = "true", title = "Area" })
</div>
<div class="form-group" style="align-self:center;">
#*<input type="submit" value="Filtrar" class="btn btn-primary" style="width:150px;" />*#
<button type="submit">Filtrar</button>
</div>
}
</fieldset>
<div id="tabless" class="card-body" style="">
<table id="table_id" class="display">
<thead>
<tr>
<th></th>
<th>ID Muestro</th>
<th>Area</th>
<th>Id Predio</th>
<th>Predio</th>
<th>Formulario</th>
<th>APLA</th>
<th>Total Parcelas</th>
</tr>
</thead>
<tbody>
#foreach (var item in ViewBag.muestreos)
{
<tr>
<td><input type="checkbox" id="cbox2" value="second_checkbox"></td>
<td>#item.IdMuestreo</td>
<td>#item.Area</td>
<td>#item.IdPredio</td>
<td>#item.NomPredio</td>
<td>#item.Formulario</td>
<td>#item.APLA</td>
<td>#item.TotalParcela</td>
</tr>
}
</tbody>
</table>
</div>
#section JavaScriptToFooter {
#Scripts.Render("https://cdn.datatables.net/1.11.3/js/jquery.dataTables.min.js")
#Scripts.Render("https://cdn.jsdelivr.net/npm/bootstrap-select#1.13.14/dist/js/bootstrap-select.min.js")
<script>
$(document).ready(function () {
$('#table_id').DataTable();
$('.selectpicker').selectpicker();
});
</script>
#Scripts.Render("~/bundles/jqueryval")
}
Controller
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using PlanificacionOperacional.Models;
using PlanificacionOperacional.Repository;
namespace PlanificacionOperacional.Controllers
{
public class MuestreoController : Controller
{
// GET: Muestreo
public ActionResult Index()
{
MuestreoRepository muestreo = new MuestreoRepository();
List<Muestreo> muestreos = muestreo.TraeMuestreo();
List<Filtro> predios = muestreo.TraePredios();
List<Filtro> zonas = muestreo.TraeZonas();
List<Filtro> areas = muestreo.TraeAreas();
ViewBag.muestreos = muestreos;
ViewBag.formularios = predios;
ViewBag.zonas = zonas;
ViewBag.areas = areas;
return View();
}
[HttpPost]
public ActionResult Filtrar(FiltroView model)
{
int predio = Convert.ToInt32(Request["predio"].ToString());
int zona = Convert.ToInt32(Request["zona"].ToString());
return View();
}
// GET: Muestreo/Details/5
public ActionResult Details(int id)
{
return View();
}
// GET: Muestreo/Create
public ActionResult Create()
{
return View();
}
// POST: Muestreo/Create
[HttpPost]
public ActionResult Create(FormCollection collection)
{
try
{
// TODO: Add insert logic here
return RedirectToAction("Index");
}
catch
{
return View();
}
}
// GET: Muestreo/Edit/5
public ActionResult Edit(int id)
{
return View();
}
// POST: Muestreo/Edit/5
[HttpPost]
public ActionResult Edit(int id, FormCollection collection)
{
try
{
// TODO: Add update logic here
return RedirectToAction("Index");
}
catch
{
return View();
}
}
// GET: Muestreo/Delete/5
public ActionResult Delete(int id)
{
return View();
}
// POST: Muestreo/Delete/5
[HttpPost]
public ActionResult Delete(int id, FormCollection collection)
{
try
{
// TODO: Add delete logic here
return RedirectToAction("Index");
}
catch
{
return View();
}
}
}
}
Model
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace PlanificacionOperacional.Models
{
public class FiltroView
{
public int zona { get; set; }
public long predio { get; set; }
public int area { get; set; }
}
}
You are using MVC but you dont have any model. You will never be able to submit form without model. So for the start create a model
public ViewModel
{
public int ZonaId {get; set;]
public int AreaId {get;set;}
.... and so on
}
and after this view
#model ViewModel
......
#Html.DropDownListFor(model=>model.PredioId, new SelectList(ViewBag.formularios, "id", "nombre"), new { #class = "selectpicker", data_live_search = "true", title = "Predio" })
#Html.DropDownListFor(model=>model.ZonaId, new SelectList(ViewBag.zonas, "id", "nombre"), new { #class = "selectpicker", data_live_search = "true", title = "Zona" })
#Html.DropDownListFor(model=>model.AreaId, new SelectList(ViewBag.areas, "id", "nombre"), new { #class = "selectpicker", data_live_search = "true", title = "Area" })
.... and so on
action
public ActionResult Filtrar(ViewModel model)
{
int predioId = model.PredioId;
int zonaId = model.ZonaId;
.... your code
}
PS.
Get rid of all your viewbags. It looks very unprofessionaly and it is hard to mantain this kind of code. Include everything in the ViewModel.
public ActionResult Index()
{
MuestreoRepository muestreo = new MuestreoRepository();
var model=new ViewModel{
muestreos = muestreo.TraeMuestreo(),
predios = muestreo.TraePredios();
zonas = muestreo.TraeZonas();
areas = muestreo.TraeAreas();
....and so on
}
return View(model);
}
I have a view with a list of checkboxes. It display fine, but on Post, the count=0 for my list. I've seen a bunch of post on SO that all say the same thing, which I've trie, but it's not working, so I must be missing something.
My ViewModels:
public class ParentViewModel
{
public ParentViewModel()
{
ClassOfTradeList = new List<CheckBoxListItem>();
}
public string Name { get; set; }
public List<CheckBoxListItem> ClassOfTradeList { get; set; }
}
public class CheckBoxListItem
{
public long Id { get; set; }
public string Name { get; set; }
public bool IsSelected { get; set; }
}
Then my View:
#model app.Models.ViewModels.ParentViewModel
// other parent fields
#for (int i = 0; i < Model.ClassOfTradeList.Count; i++)
{
#Html.CheckBoxFor(m => m.ClassOfTradeList[i].IsSelected)
#Html.HiddenFor(m => m.ClassOfTradeList[i].Id)
#Html.LabelFor(m => m.ClassOfTradeList[i].IsSelected, Model.ClassOfTradeList[i].Name)
<br />
}
My Post in the controller:
public ActionResult ParentReturn(ParentViewModel model)
{
}
My Get:
[HttpGet]
public ActionResult Parent()
{
var model = new ParentViewModel();
//fill in properties here
model.ClassOfTradeList = ClassOfTradeList();
return View(model);
}
private List<CheckBoxListItem> ClassOfTradeList()
{
var classofTrades = _tradeRepo.GetAll().Where(c => c.IsDeleted == false).ToList();
var classOfTradeList = new List<CheckBoxListItem>();
classOfTradeList = classofTrades.Select(c => new CheckBoxListItem
{
Name = c.Name,
Id = c.Id
}).ToList();
return classOfTradeList;
}
So when I get back to the controller, the model.ClassOfTrades.Count =0. What am I missing?
I figured it out. When I first was trying to fix this, I put:
#Html.HiddenFor(m => m.ClassOfTradeList)
in the beginning of the View. It was overriding my hiddenfor of the id later on in the view.
Thanks all for your help. So removing that and keeping the code I have posted made it work.
You should probably use "Model.ClassOfTradeList[i].Name" instead of Id.
#using (Html.BeginForm("ParentReturn", "Home", FormMethod.Post))
{
for (int i = 0; i < Model.ClassOfTradeList.Count; i++)
{
#Html.CheckBoxFor(model => Model.ClassOfTradeList[i].IsSelected);
#Html.HiddenFor(model => Model.ClassOfTradeList[i].Name);
#Html.LabelFor(model => Model.ClassOfTradeList[i].IsSelected, Model.ClassOfTradeList[i].Name);
<br />
}
<input type="submit" value="click" />
}
https://dotnetfiddle.net/C0trTW
this is my controller view
public ActionResult rb()
{
subject ts = new subject();
ts.subjectlist = db.tbSubjs.ToList();
ts.selectsubj = "";
return View(ts);
}
[HttpPost]
public ActionResult rb(subject sj, FormCollection frm)
{
if (ModelState.IsValid)
{
var selectsubj = sj.selectsubj;
string getcode = frm["subj"];
ViewBag.ssss = getcode;
}
return View("Index");
}
and this is my class
public class subject
{
public List<tbSubj> subjectlist { get; set; }
public string selectsubj { get; set; }
}
Here is my code for the radio button
<div style="text-align: left">
#using (Html.BeginForm("rb", "Home"))
{
<div>------</div>
foreach (var ts in Model.subjectlist)
{
<div>
#Html.Label(ts.SubjCode)
#Html.RadioButtonFor(m => m.subjectlist, ts.SubjCode)
</div>
}
foreach (var getsubj in Model.subjectlist)
{
<div>------------------</div>
<div>
#getsubj.SubjCode
#Html.RadioButton("subj", getsubj.SubjCode)
</div>
}
<br />
<input id="Submit" type="submit" value="Submit" />
}
</div>
and i want to set a value in my textbox in this view by getting the value of my radio button.
#model ATM.Models.subject
#{
ViewBag.Title = "rb";
}
<h2>rb</h2>
#Html.TextBox(m => m.selectsubj)
If someone is willing to help me please help me.
Assuming that your action actually looks more like the following:
[HttpPost]
public ActionResult rb(subject sj, FormCollection frm)
{
if (ModelState.IsValid)
{
var selectsubj = sj.selectsubj;
string getcode = frm["subj"];
ViewBag.ssss = getcode;
return View("view_with_textbox");
}
return View("Index");
}
You could do this:
[HttpPost]
public ActionResult rb(subject sj, FormCollection frm)
{
if (ModelState.IsValid)
{
var selectsubj = sj.selectsubj;
string getcode = frm["subj"];
var model = new ATM.Models.subject()
{
selectsubj = getcode
};
return View("view_with_textbox", model);
}
return View("Index");
}
Thereby passing the value in via the model.
I am a new to MVC and still learning! I am trying to create a very basic App in my web which allows users to convert money value according to their preference. I made the web APi and was successful to call the service to my forms. However, in my controller I managed to get the currencies (names) to the index view, but cannot post the form back once entering a value in the text box to generate the partial view! What am I doing wrong in my codes?!
Currency Controller
namespace MVC_ATM.Controllers
{
public class CurrencyController : Controller
{
[HttpGet]
// GET: Currency
public ActionResult Index()
{
CurrenciesClient Cur = new CurrenciesClient();
var listCurrency = Cur.findAll();
SelectList list = new SelectList(listCurrency,"Id", "CurrencyName");
ViewBag.listCurrencies = list;
return View();
}
[HttpPost]
public ActionResult Index(Currencies cur)
{
if (!ModelState.IsValid)
{
string errors = string.Join("<br />", ModelState.Values
.SelectMany(x => x.Errors)
.Select(x => x.ErrorMessage));
return new ContentResult { Content = errors };
var rate = Convert.ToDecimal(cur.ConversionRate);
if (cur.CurrencyName == cur.CurrencyName)
{
ModelState.AddModelError("CurrencyCountry", "Can't make the conversion for the same value");
}
else if (cur.CurrencyName != cur.CurrencyName)
{
foreach (var currency in cur.CurrencyName)
{
ViewBag.Theresult = rate * cur.Value;
}
return PartialView("_CurrencyValue");
}
}
return View();
}
}
}
Currencies Model
namespace Project.Model
{
public class Currencies
{
public int Id { get; set; }
public string CurrencyName { get; set; }
public string CurrencyCountry {get; set;}
public decimal Value { get; set; }
public string ConversionRate { get; set; }
}
}
Index View
#model Project.Model.Currencies
#{
ViewBag.Title = "Index";
}
<h2>Currency</h2>
<body>
<div class="converter">
Convert: #Html.TextBoxFor(m => m.ConversionRate, new { #size = "5" })
<div class="form-group">
#Html.Label("Convert from", new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.DropDownList("Currency List", ViewBag.listCurrencies as SelectList, "Please Select a currency")
</div>
</div>
<div class="form-group">
#Html.Label("Convert to", new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.DropDownList("Currency List", ViewBag.listCurrencies as SelectList, "Please Select a currency")
</div>
</div>
<div>
<button type="submit" class="btn btn-primary">Convert</button>
</div>
</div>
</body>
Couple of things to notice, is the POST action and missing form tag in the view . You created a POST action that accepts Currencies model but the form doesn't post that. Only ConversionRate will bind to the model. To get the "Currency From" and "Currency To" and the "Conversion Rate" you will require a different approach/small changes.
ConversionModel.cs a new Model for index page that will capture your required fields.
public class ConversionModel
{
[Required]//decimal would be better but up to you requirement
public decimal ConversionRate { get; set; }
[Required]
public int FromCurrencyId {get;set;}
public SelectList FromCurrencies {get;set;}
[Required]
public int ToCurrencyId {get;set;}
public SelectList ToCurrencies {get;set;}
}
Get: while there is nothing wrong with what you've done, lets use a model approach and tightly bind it.
public ActionResult Index()
{
CurrenciesClient Cur = new CurrenciesClient();
var listCurrency = Cur.findAll();
ConversionModel model = new ConversionModel();
model.FromCurrencies = new SelectList(listCurrency,"Id", "CurrencyName");
model.ToCurrencies = new SelectList(listCurrency,"Id", "CurrencyName");
return View(model);
}
Post: Important thing here to notice is the SelectList will not be posted back. Only the ConversionRate, FromCurrencyId and ToCurrencyId are sent back not the Lists. If error occurs you will need to rebuild the lists and send it back in the model.
[HttpPost]
public ActionResult Index(ConversionModel curModel)
{
if(ModelState.IsValid)
{
if(curModel.FromCurrencyId ==curModel.ToCurrencyId)
{
//do something if same currecnies and return.
}
else
{
//Get the currencyList with rates from db
//use currency ToCurrencyId and FromCurrencyId to fetch the 2 currencies
// perform conversion with curModel.ConversionRate with existing logic
}
}
//Don'f forget to rebuild the Select Lists...
return View(curModel);
}
View:
#model Project.Model.ConversionModel
#{
ViewBag.Title = "Index";
}
#using (Html.BeginForm("Index", "Currency", FormMethod.Post)
{
#Html.TextBoxFor(m => m.ConversionRate, new { #size = "5" })
#* Please check the syntax *#
#Html.DropDownListFor(m => m.FromCurrencyId , Model.FromCurrencies as SelectList)
#Html.DropDownListFor(m => m.ToCurrencyId , Model.ToCurrencies as SelectList)
<button type="submit" class="btn btn-primary">Convert</button>
}
Not a CUT_COPY_PASTE. please do check for errors if any. It is only an approach.
ajax POST probably the next thing to learn... Let us know.
You need to put your items inside a form like this:
#using (Html.BeginForm("Index", "Currency", FormMethod.Post)
{
// Your form items
}
Trying to display only one comment from the text box in the partial view.
To get some data you need the Session Controller:
private ConferenceContext context = new ConferenceContext();
//
// GET: /Session/
public ActionResult Index()
{
ConferenceContext context = new ConferenceContext();
List<Session> sessions = context.Sessions.ToList();
return View(sessions);
}
//
// GET: /Session/Details/5
public ActionResult Details(int id = 0)
{
Session session = context.Sessions.Find(id);
if (session == null)
{
return HttpNotFound();
}
return View(session);
}
Details View in the Session Folder:
#model Conference.Models.Session
<h3>
#Model.Title
</h3>
<div>
#Model.Abstract
</div>
#Html.Action("_GetForSession", "Comment", new { SessionID = Model.SessionID })
Then the CommentController, which is using the partial view _GetForSession to display the text from the Text Box:
ConferenceContext context = new ConferenceContext();
public PartialViewResult _GetForSession(Int32 sessionID)
{
ViewBag.SessionID = sessionID;
List<Comment> comments = context.Comments.Where(c => c.SessionID == sessionID).ToList();
return PartialView("_GetForSession", comments);
}
[ChildActionOnly()]
public PartialViewResult _CommentForm(Int32 sessionID)
{
Comment comment = new Comment() { SessionID = sessionID };
return PartialView("_CommentForm", comment);
}
[ValidateAntiForgeryToken()]
public PartialViewResult _Submit(Comment comment)
{
context.Comments.Add(comment);
context.SaveChanges();
List<Comment> comments = context.Comments.Where(c => c.SessionID == comment.SessionID).ToList();
ViewBag.SessionID = comment.SessionID;
return PartialView("_GetForSession", comments);
}
Here is the _GetForSession View from the Comment folder:
#model IEnumerable<Conference.Models.Comment>
<div id="comments">
<ul>
#foreach (var comment in Model)
{
<li>#comment.Content</li>
}
</ul>
#using(Ajax.BeginForm("_Submit", "Comment", new AjaxOptions() { UpdateTargetId = "comments" }))
{
#Html.AntiForgeryToken();
#Html.Action("_CommentForm", new { SessionID = ViewBag.SessionID })
}
</div>
The _GetForSession gets its data from the _CommentForm in the Comment folder:
#model Conference.Models.Comment
#Html.HiddenFor(m => m.SessionID)
<div>
#Html.LabelFor(m => m.Content)
#Html.EditorFor(m => m.Content)
</div>
<button type="submit">Submit Comment</button>
Now the main Context would be coming from ConferenceContext in the Models:
public class ConferenceContext : DbContext
{
public DbSet<Session> Sessions { get; set; }
public DbSet<Speaker> Speakers { get; set; }
public DbSet<Comment> Comments { get; set; }
}
And the Context itself from the ConferenceContextInitializer:
public class ConferenceContextInitializer : DropCreateDatabaseAlways<ConferenceContext>
{
protected override void Seed(ConferenceContext context)
{
context.Sessions.Add(
new Session()
{
Title = "Partial View",
Abstract = "View Within the Main",
Speaker = context.Speakers.Add(new Speaker()
{
Name = "John Smith",
EmailAddress = "johnsmith#nowhere.com"
})
});
context.SaveChanges();
}
}
So, my question is can it be possible to display only one comment in the partial view not two?