I've got a very basic MVC project that does maths operations (+ - / *) of 2 numbers
for some reasons my view is not updating after postback
here is my controller
namespace MathsAppMVC.Controllers
{
public class HomeController : Controller
{
MathsServiceClient loClient = new MathsServiceClient();
Int32 loNum1 = 0;
Int32 loNum2 = 0;
//Int32 result = 0;
String locOperation = "Add";
public ActionResult Index()
{
var model = new MathsModel
{
Number1 = loNum1,
Number2 = loNum2,
//Result = result,
MathsOperation = locOperation
};
return View(model);
}
[HttpGet]
public ActionResult MathsOperation()
{
return View();
}
[HttpPost]
public ActionResult MathsOperation(MathsModel mathsModel)
{
loNum1 = mathsModel.Number1;
loNum2 = mathsModel.Number2;
locOperation = mathsModel.MathsOperation;
if (locOperation == "Add")
{
mathsModel.Result = loClient.add(loNum1, loNum2);
}
else if (locOperation == "Subtract")
{
mathsModel.Result = loClient.subtract(loNum1, loNum2);
}
else if (locOperation == "Multiple")
{
mathsModel.Result = loClient.multiple(loNum1, loNum2);
}
else
if (locOperation == "Divide")
{
mathsModel.Result = loClient.divide(loNum1, loNum2);
}
if (ModelState.IsValid)
{
return View("Index", mathsModel);
}
else
{
return View("Index");
}
}
}
}
HERE IS VIEW
#model MathsAppMVC.Models.MathsModel
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#using (Html.BeginForm("MathsOperation", "Home", FormMethod.Post, new { }))
{
<fieldset>
<legend>Maths:</legend>
<div>#Html.LabelFor(u=>u.MathsOperation)</div>
<div>#Html.DropDownListFor(u => u.MathsOperation, new SelectList(
new List<Object>
{
new { value = "Add" , text = "Add" },
new { value = "Subtract" , text = "Subtract" },
new { value = "Multiple" , text = "Multiple"},
new { value = "Divide" , text = "Divide"}
},
"value",
"text",
0))
</div>
<div>#Html.LabelFor(u=>u.Number1)</div>
<div>#Html.TextBoxFor(u=>u.Number1)</div>
<div>#Html.LabelFor(u=>u.Number2)</div>
<div>#Html.TextBoxFor(u=>u.Number2)</div>
<div>#Html.LabelFor(u=>u.Result)</div>
<div>#Html.DisplayTextFor(u=>u.Result)</div>
<input type="submit" value ="Calculate" />
<input type="reset" value ="Clear" />
</fieldset>
}
In the view after postback for what ever reason the Result is always 0.
Some one please help?
I hate to post this as an answer, but that's all I can do with my amount of reputation. I literally copied and pasted your code into a new MVC project and it works fine. Can you post your MathsServiceClient code?
Related
This error appears when I'm training to post reply message and insert it in Replies Table using message id , I think the problem from the View when the id is calling
#using (Html.BeginForm("ReplyMessage", "Messages", FormMethod.Post, new
{ id = "form-reply-message", messageId = #ViewBag.MessageId }))
Any idea what I should change
Controller Get Method:
public ActionResult ReplyMessage(int? Id, int? page)
{
MessageReplyViewModel vm = new MessageReplyViewModel();
if (Id != null)
{
var replies = dbContext.Replies.Where(x => x.MessageId == Id.Value).OrderByDescending(x => x.ReplyDateTime).ToList();
if (replies != null)
{
foreach (var rep in replies)
{
MessageReplyViewModel.MessageReply reply = new MessageReplyViewModel.MessageReply();
reply.MessageId = rep.MessageId;
reply.Id = rep.Id;
reply.ReplyMessage = rep.ReplyMessage;
reply.ReplyDateTime = rep.ReplyDateTime;
reply.MessageDetails = dbContext.Messages.Where(x => x.Id == rep.MessageId).Select(s => s.MessageToPost).FirstOrDefault();
reply.ReplyFrom = rep.ReplyFrom;
vm.Replies.Add(reply);
}
}
else
{
vm.Replies.Add(null);
}
ViewBag.MessageId = Id.Value;
}
return View(vm);
Controller PostMethod :
[HttpPost]
[Authorize]
public ActionResult ReplyMessage(MessageReplyViewModel vm, int messageId)
{
if (vm.Reply.ReplyMessage != null)
{
Models.Reply _reply = new Models.Reply();
_reply.ReplyDateTime = DateTime.Now;
_reply.MessageId = messageId;
_reply.ReplyMessage = vm.Reply.ReplyMessage;
dbContext.Replies.Add(_reply);
dbContext.SaveChanges();
}
return RedirectToAction("Index", "Message");
View :
#using (Html.BeginForm("ReplyMessage", "Messages", FormMethod.Post, new { id = "form-reply-message", messageId = #ViewBag.MessageId }))
{
if (!ViewData.ModelState.IsValid)
{
#Html.ValidationSummary(true)
}
#Html.HiddenFor(model => model.Reply.MessageId);
#Html.TextAreaFor(p => p.Reply.ReplyMessage, new { #rows = 2, #class = "form-control" })
#Html.ValidationMessageFor(model => model.Reply.ReplyMessage)
<input type="submit" class="btn btn-primary btn-success" value="Reply" id="btn-reply-message">
}
You may have to bind it using [FromQuery] attribute here:
public ActionResult ReplyMessage(MessageReplyViewModel vm, [FromQuery("messageId")] int messageId)
{
........
}
This attributes reads the values after the "?" operator in the URL. Hopefully it will help!
I am attempting to implement paging and sorting into my Index view. I am following the example at http://www.codeguru.com/csharp/.net/net_asp/mvc/implementing-sorting-and-paging-in-asp.net-mvc.html however my work is neither paging or sorting. I am not sure where I went wrong.
My Index view is passed a parameter when accessed so I did modify it a little however it should not have cause it to do nothing.
My PagingInfo viewModel used for the paging and sorting is as followings.
public class PagingInfo
{
public string SortField { get; set; }
public string SortDirection { get; set; }
public int PageSize { get; set; }
public int PageCount { get; set; }
public int CurrentPageIndex { get; set; }
}
My controller has
public ActionResult Index(int id)
{
DeviceLogIndex vm = new DeviceLogIndex();
var devicelogs = db.DeviceLogs
.Include(d => d.Device)
.Include(d => d.DeviceLogType)
.Include(d => d.Device.ManufacturerModel)
.Where(d => d.DeviceID == id);
{
PagingInfo info = new PagingInfo();
info.SortField = "DeviceLog";
info.SortDirection = "ascending";
info.PageSize = 4;
info.PageCount = Convert.ToInt32(Math.Ceiling((double)(db.DeviceLogs.Count()/info.PageSize)));
// info.PageCount +=1;
info.CurrentPageIndex = 0;
var query = devicelogs.OrderBy(c => c.DeviceLogID).Take(info.PageSize);
ViewBag.PagingInfo = info;
vm.DeviceLogs = query.ToList();
Device model = db.Devices.Find(id);
model.DeviceID= id;
vm.MyDeviceID = id;
return View(vm);
}
}
[HttpPost]
public ActionResult Index(PagingInfo info, int id)
{
DeviceLogIndex vm = new DeviceLogIndex();
var devicelogs = db.DeviceLogs
.Include(d => d.Device)
.Include(d => d.DeviceLogType)
.Include(d => d.Device.ManufacturerModel)
.Where(d => d.DeviceID == id);
{
IQueryable<DeviceLog> query = null;
switch (info.SortField)
{
case "EntryDate":
query = (info.SortDirection == "ascending" ?
devicelogs.OrderBy(c => c.EntryDate) :
devicelogs.OrderByDescending(c => c.EntryDate));
break;
case "LogType":
query = (info.SortDirection == "ascending" ?
devicelogs.OrderBy(c => c.DeviceLogType) :
devicelogs.OrderByDescending(c => c.DeviceLogType));
break;
}
query = query.Skip(info.CurrentPageIndex * info.PageSize).Take(info.PageSize);
ViewBag.PagingInfo = info;
vm.MyDeviceID = id;
vm.DeviceLogs = query.ToList();
return View(vm);
}
}
And my View contains these parts
#model AQB_MON.ViewModels.DeviceLogIndex
<script>
$(document).ready(function () {
$(".header").click(function (evt) {
var sortfield = $(evt.target).data("sortfield");
if ($("#SortField").val() == sortfield) {
if ($("#SortDirection").val() == "ascending") {
$("#SortDirection").val("descending");
}
else {
$("#SortDirection").val("ascending");
}
}
else {
$("#SortField").val(sortfield);
$("#SortDirection").val("ascending");
}
evt.preventDefault();
$("form").submit();
});
$(".pager").click(function (evt) {
var pageindex = $(evt.target).data("pageindex");
$("#CurrentPageIndex").val(pageindex);
evt.preventDefault();
$("form").submit();
});
});
</script>
#{
ViewBag.Title = "Index";
}
#{
AQB_MON.ViewModels.PagingInfo info = ViewBag.PagingInfo;
}
<h2>Index</h2>
<p>
#Html.ActionLink("Create New", "Create", new { id = Model.MyDeviceID})
</p>
#using (Html.BeginForm("Index", "DeviceLog", FormMethod.Get))
{
#Html.Hidden("SortField", info.SortField)
#Html.Hidden("SortDirection", info.SortDirection)
#Html.Hidden("PageCount", info.PageCount)
#Html.Hidden("PageSize", info.PageSize)
#Html.Hidden("CurrentPageIndex", info.CurrentPageIndex)
to set the Headers that are sortable -
<th>
<a href="#" data-sortfield="LogType"
class="header">Device Log Type</a>
</th>
<th>
<a href="#" data-sortfield="EntryDate"
class="header">Entry Date</a>
</th>
for the paging -
<td>
#for (var i = 0; i < info.PageCount; i++)
{
if (i == info.CurrentPageIndex)
{
<span>#(i + 1)</span>
}
else
{
<a href="#" data-pageindex="#i"
class="pager">#(i + 1)</a>
}
}
</td>
It's a lot of code that does not seem to do anything. Just confused.
My code is as followed and the error message are not displayed:
Index.cshtml
#model WebApp.Models.OrderItems
#using (Html.BeginForm("SaveToDB", "Home", FormMethod.Post, new { #class = "form-group", role = "form" }))
{
#Html.Partial("Information")
}
Partial : Information.cshtml
#model WebApp.Models.OrderItems
<div class="col-lg-4">
<div class="form-group">
<label for="input1" class="col-lg-4 control-label">#Html.LabelFor(model => model.CLInfo.ClientName)</label>
#Html.EditorFor(model => model.CLInfo.ClientName, new { style = "width:250px" })
#Html.ValidationMessageFor(model => model.CLInfo.ClientName)
</div>
</div>
Model :
public class OrderItems
{
public InfoCLInfo{ get; set; }
}
Model : the class for Infos
public class Info
{
[Display(Name = "Client Name")]
[Required]
public string ClientName{ get; set; }
}
The controller
[HttpPost]
[MultipleButton(Name = "action", Argument = "SaveToDB")]
public ActionResult SaveToDB(OrderItems Client)
{
var errors = ModelState.Values.SelectMany(v => v.Errors);
if (ModelState.IsValid)
{
if (_db == null)
_db = new OrderDB();
OrderItems ClientOrig = Session["Clientobj"] as OrderItems;
ClientOrig.CLInfo = Client.CLInfo;
Session["Clientobj"] = null;
}
return RedirectToAction("Index", "Home");
}
[Authorize]
public ActionResult Index (OrderItems Client)
{
int ClientID = Convert.ToInt32(Session["Client"]);
if ClientID == 0)
{
ClientID = 2;
Session["Client"] = ClientID;
}
if (Session["Clientobj"] == null)
{
Client = new OrderItems();
Client.CLOrderID = 123;
Session["Clientobj"] = Client;
}
else
{
Client = Session["Clientobj"] as OrderItems
}
return View(Client);
}
on post the ModelState.IsValid return false which true, but I don't have any message to tell the user where is the error to be fixed.
I tried to add : #Html.ValidationSummary(true) after the BeginForm , but it didn
Any idea please
Thanks
You cannot use RedirectToAction if you want to retain your model state. All errors and what not are kept in the ModelState object, and when you redirect to action it's performing a new get action, which starts fresh with a clean slate.
You need to return the view like you do in the original action.
Is it possible to set the value of the textbox using the controller? I have the following form in my View:
#Html.TextBoxFor(Models => Models.techNo, new { #class="form-control maintain-text",
placeholder="Technician No..."})
<button type="submit" id="search" name="SubmitButton" value="search" class="btn btn-default">Search</button>
<td>First Name :</td>
<td>#Html.TextBoxFor(Models => Models.firstName, new { #class = "form-control", style = "width:380px;", disabled = "disabled" })</td>
<td>Last Name :</td>
<td>#Html.TextBoxFor(Models => Models.lastName, new { #class = "form-control", style = "width:380px;", disabled = "disabled" })</td>
Model:
public string techNo { get; set; }
public string firstName { get; set; }
public string lastName { get; set; }
Controller:
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult ProcessTech(string SubmitButton)
{
TechnicianFacade _oTechFacade = new TechnicianFacade();
Technician _oTechnician = new Technician();
string fName = Request.Form["firstName"].ToString().ToUpper();
string lName = Request.Form["lastName"].ToString().ToUpper();
switch (SubmitButton)
{
case "save": //add new technician
{
}
break;
case "update": //update technician details
{
}
break;
case "search": //search technician
{
try {
string id = Request.Form["techNo"].ToString().ToUpper();
if (isValid(id, "technician") == false) //search the id from the database
{
//do nothing
}
else //if id is valid
{
var tech = _oTechFacade.getTechnicians(id, _oAppSetting.ConnectionString)[0]; //data from the database
string fNameStr = tech.GetType().GetProperty("FIRSTNAME").GetValue(tech, null).ToString();
string lNameStr = tech.GetType().GetProperty("LASTNAME").GetValue(tech, null).ToString();
//When the the ID is found,
//these are the values of the firstName & lastName that I want to set to the View
//Is it possible to set the values of the textboxes from here?
}
}
catch (Exception ex) { throw ex; }
}
break;
case "delete":
{
}
break;
}
return View("Index");
}
Basically, after searching the ID(assuming its valid) I want to grab the firstName & lastName data from the database and then display it to the View for updating or deleting. I've tried ViewBag, ViewData, and TempData but all are not working for me.
EDIT:
#model Maintenance_.Models.IndexModel
#{
ViewBag.Title = "Technician";
}
<div id="page-wrapper">
<div class = "row">
<div class = "col-lg-12">
<h1 class= "page-header"> Technician </h1>
</div>
</div>
....
As i see your code, you are using explicitly typed view and using same view for insert and update. And in this case you must return model to your view like that:
[HttpPost]
public ActionResult ProcessTech(string SubmitButton)
{
TechnicianFacade _oTechFacade = new TechnicianFacade();
Technician _oTechnician = new Technician();
string fName = Request.Form["firstName"].ToString().ToUpper();
string lName = Request.Form["lastName"].ToString().ToUpper();
YourModelName model = new YourModelName ();
switch (SubmitButton)
{
case "save": //add new technician
{
}
break;
case "update": //update technician details
{
}
break;
case "search": //search technician
{
try {
string id = Request.Form["techNo"].ToString().ToUpper();
if (isValid(id, "technician") == false) //search the id from the database
{
//do nothing
}
else //if id is valid
{
var tech = _oTechFacade.getTechnicians(id, _oAppSetting.ConnectionString)[0]; //data from the database
string fNameStr = tech.GetType().GetProperty("FIRSTNAME").GetValue(tech, null).ToString();
string lNameStr = tech.GetType().GetProperty("LASTNAME").GetValue(tech, null).ToString();
model.firstname = fNameStr;
model.lastname = lNameStr;
//When the the ID is found,
//these are the values of the firstName & lastName that I want to set to the View
//Is it possible to set the values of the textboxes from here?
}
}
catch (Exception ex) { throw ex; }
}
break;
case "delete":
{
}
break;
}
return View("Index",model);
}
This line:
return View("Index");
is not passing a model to the Index view.
You need to create an instance of your view, and set its properties:
var model = new IndexModel();
...
else //if id is valid
{
var tech = _oTechFacade.getTechnicians(id, _oAppSetting.ConnectionString)[0]; //data from the database
string fNameStr = tech.GetType().GetProperty("FIRSTNAME").GetValue(tech, null).ToString();
string lNameStr = tech.GetType().GetProperty("LASTNAME").GetValue(tech, null).ToString();
//When the the ID is found, we populate our model
//so it can be displayed
model.firstname = fNameStr;
model.lastname = lNameStr;
}
Now you can do:
return View("Index", model);
#Brendan Green answer is correct you need pass model to the view Also then you can set text box value using add new property to Html Helper.
#Html.TextBoxFor(Models => Models.firstName, new { #class = "form-control", style = "width:380px;", disabled = "disabled", #value = Model.firstName })
Note here value set by #value property
Update:
Change < button > element to < input type="submit" > also change the id to SubmitButton and Name also SubmitButton (id and Name values same is good)then try again seems to problem with your switch statement. Debug it then you can see what happen.
Also pass model to view and Name of the View should be Index then view correctly calling.
Essentially I have a HtmlPasswordFor(m => EmployeeID), I have a button called "Go". Once I hit the Go textbox, I actually do not want the password to disappear on the or have the field password to be cleared.
How would I do this?
BEFORE
AFTER
I do not want the my employeeid to reset. I want to keep the passwords in ****'s, but I'll need the password on my next post call.
Controller
[HttpGet]
public ActionResult MainForm()
{
var model = new VTViewModel();
return View(model);
}
[HttpPost]
public ActionResult MainForm(VTViewModel model, string buttontype)
{
if (ModelState.IsValid)
{
string EmployeeID = (Convert.ToInt64(model.EmployeeBinaryID, 2)).ToString();
if (buttontype == "Go")
{
// GET Fields depending on the serial number.
model.ListFields = logic_model.getFormInfo(model.SerialNumber, EmployeeID);
if (model.ListFields[0].return_num == "0")
{
model.Go = true;
// Set Process
// Set Header Token
// Set Header Title
ViewData["HEADER"] = model.ListFields[0].HeaderName + " | " + model.ListFields[0].TubeType + " | " + model.ListFields[0].ProductLine;
}
else
{
model.DisplayMessage = helper.checkErrors(model.ListFields[0].return_num);
}
}
else if (buttontype == "Submit")
{
model.HeaderToken = model.ListFields[0].HeaderToken;
string header = model.HeaderToken;
string check = "";
string return_num = model.ListFields[0].return_num;
// If the submission worked
//SUBMIT HERE INTO DB then Clear
List<string> values_to_submit = new List<string>(); // Creates a list to store the values to submit
for (int i = 0; i < model.ListFields.Count; i++)
{
// Fills in the hidden values.
if (model.ListFields[i].isHidden)
{
if (model.ListFields[i].Token == "SNT" || model.ListFields[i].Token == "SNC")
{
model.ListFields[i].Value = model.SerialNumber;
}
else if (model.ListFields[i].Token == "USR")
{
model.ListFields[i].Value = EmployeeID;
}
else if (model.ListFields[i].Token == "TMS")
{
model.ListFields[i].Value = "0";
}
}
// If it is a check box do the right conversion.
if (model.ListFields[i].DataType == "DATA-CKBOX")
{
//string convertedValue = helper.trueFalseStringtToIntBool(model.ListFields[i].Value);
string convertedValue = helper.boolToInt(model.ListFields[i].BoolValue).ToString();
model.ListFields[i].Value = convertedValue;
}
values_to_submit.Add(model.ListFields[i].Token + model.ListFields[i].Value);
}
check = logic_model.helperSubmit(values_to_submit, header, 1);
if (check == "Submitted")
{
ModelState.Clear();
VTViewModel clear_model = new VTViewModel(); // Creates an empty model
clear_model.DisplayMessage = "Submitted\n" + model.SerialNumber + "\n" + DateTime.Now;
return View(clear_model);
}
else
{
model.DisplayMessage = check; // Sets the display message to the error.
}
}
else if (buttontype == "Clear")
{
// Clears the screen and model
ModelState.Clear();
VTViewModel clear_model = new VTViewModel(); // Creates an empty model
return View(clear_model);
}
}
return View(model);
}
View
div>
<fieldset>
<table id="main_table">
<tr>
<td>#Html.LabelFor(m => m.SerialNumber)</td>
<td>#Html.LabelFor(m => m.EmployeeBinaryID)</td>
</tr>
<tr>
<td>#Html.TextBoxFor(m => m.SerialNumber)</td>
<td>#Html.PasswordFor(m => m.EmployeeBinaryID, new { autocomplete = "off" }) </td>
</tr>
<tr><td><input type="submit" value="Go" name="buttontype" class="submit_button" id="btn"/><br /><br /></td></tr>
</table>
</fieldset>
<br />
Thanks
Html.PasswordFor will never render the value, probably for security reasons. You can work around this, but you have to use Html.EditorFor instead, decorate the EmployeeID property with [DataType(DataType.Password)] and add the following editor template at ~/Views/Shared/EditorTemplates/Password.cshtml
#Html.Password("", ViewData.TemplateInfo.FormattedModelValue, new { #class = "text-box single-line password" })
You could also use [UIHint] and create a template for that particular property only.