MVC HttpPost receives a null parameter - c#

The controller file in the application HomeController.cs, defines the two controls SetPowerOff and [HttppPost] SetPowerOff.
public ActionResult SetPowerOff(int ID, string deepness)
{
.............
if (Request.IsAjaxRequest())
{
var viewModel = new HomeSetPowerOffViewModel()
{
//List of devices
Devicelist = list,
age = 18
};
return PartialView("_SetPowerOff", viewModel);
}
else
{
return HttpNotFound();
}
}
[HttpPost]
public ActionResult SetPowerOff(HomeSetPowerOffViewModel homeSetPowerOffViewModel)
{
}
The Partial View returns the devices in a list.
#using (Html.BeginForm("SetPowerOff", "Home", FormMethod.Post, new { #class = "form-horizontal" }))
{
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">X</button>
<h3 id="myModalLabel">Devices information</h3>
</div>
<div class="modal-body ">
<div class="row-fluid">
<div class="span12">
<ul>
#foreach (var devices in Model.Devicelist)
{ <li>
#devices.Name;
</li>
}
</ul>
</div>
</div>
</div>
<div class="modal-footer">
#Html.ActionLink("Cancel", "Index", "Home", new { #class = "btn btn-danger" })
<button type="submit" class="btn btn-success">
Ok
</button>
</div>
}
After I press the Ok button on the Partial View it goes to the HttpPost request. Here the homeSetPowerOffViewModel received is null and the age is 0. I would very much like to know why is resetting them.
Thanks for your time!

you dont have any inputs in your form so there is nothing to submit

Your view<form>does not contain the form field like <input><select><textarea> for the age field.
So when you submit, it will be set to default integer value 0
Assuming age property of HomeSetPowerOffViewModel is a type of integer (int)

On post you receive hidden or any other input fields ( dropdowns, textbox and so on ). There is no such fields in your form. ( you are not filling the model in any way )
Althought, you can submit with ajax and you can send whatever you want to your controller

Related

Pass a list from get method (or from a view) to post method ASP .NET MVC

I apologize if the heading is not very clear.
So, what I want to do is following.
I have a model class called "Class" that contains a list of "Students". I have a view that shows a checklist of Students. From that checklist I want to pass the selected students back to controller, where I will update the Database and my class will have new students and the added students will have a new class.
Here is what I have done so far but now I am stuck. Thanks in advance.
These are my controller actions
[HttpGet]
public ActionResult AddStudents(int? id)
{
List<Student> students = (from std in db.Students
where std.St_cl_fk_id == null select std).ToList();
//ViewBag.students = students;
return View("Add_Students",students);
}
[HttpPost, ActionName("AddStudents")]
public ActionResult AddStudentsPost(int? id,List<Student> students)
{
if(ModelState.IsValid)
{
var temp = id;
Class #class = db.Classes.Find(id);
foreach (var item in students)
{
if (Request.Form[item.St_id.ToString()] != null)
{
#class.Students.Add(item);
}
}
db.Entry(#class).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index", "Classes");
}
return View("Add_Student");
}
Here is my view
#model IEnumerable<GMASchoolProject.Models.Student>
#{
ViewBag.Title = "Add_Students";
}
<h4>Student List</h4>
#using (Html.BeginForm())
{
<div class="row">
<div class="col-lg-8 col-lg-offset-2">
<div class="panel panel-default">
<div class="panel-heading">
Check Students
</div>
<div class="form-group">
<div class="col-md-10">
<table>
#foreach (var std in Model)
{
<tr>
<td><input type="checkbox" name="#std.St_id" value="#std.IsSelected" /></td>
<td>#Html.Label((string)std.St_name)</td>
</tr>
}
</table>
</div>
</div>
<div class="form-group" style="margin:15px,0,15px,0;">
<div class="col-md-offset-5 col-md-2">
<input type="submit" value="Add Students" class="btn btn-primary" />
</div>
</div>
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index", null, new { #class = "btn btn-danger" })
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Please let me know if there is anything else that I am doing wrong, I am a newbie in this area. THanks
First, instead of binding the view to a list of students, bind the model to your Class object that has a list of students in it. That way, when you submit (post), you are sending the whole Model object into the Controller.
Change your AddStudentsPost method to take in Class object and do your logic there.
Finally, change the name of the "Class" object to something else, such as, "Course". Class should be reserved for actual classes so not to cause confusion.
You aren't far off, so keep going

Html.BeginForm does not return correct instance of Model

I am having a hard time figuring out how to make Html.BeginForm to return the current Instance of Model instead of a new instance.
To explain what is wrong, when i write somthing in the TextBoxFor() and click on the submit button in the html.beginform(), it correctly does the AddStatus() and places it in the statusDict with the right key and is displayed on the right side in the view in the foreach loop. When i then click on the "fortsæt" button on the right side, it corrects loads the value into the TextBoxFor since i have it default to Model.MailTitel. Now i want to change what is in the Model.Mailtitel and when i click submit i want it to return this specific instance of the model to the controller but with a new value for MailTitel and since this would be a instance of the model already in the statusDict, it should just update the #status.Value.MailTitel. However since Html.BeginForm() returns a new instance of the model and thus is not in the statusDict which leads to it being added to it and thus shows as a new card on the right side.
So my question is: How to make Html.BeginForm() return the same instance of Model as the controller gave to the view?
Code:
View:
#using DS_Prototype.Models
<!--Left side - Info filling -->
<div class="split left">
#using (Html.BeginForm("Submit", "Home", FormMethod.Post))
{
#Html.AntiForgeryToken() // helps mitigate against cross-site request forgery
#Html.TextBoxFor(Model => Model.MailTitel, new { #Value = Model.MailTitel })
<button type="submit" class="btn btn-block btn-login">Submit</button>
}
</div>
<!--Right side - Status overview -->
<div class="split right">
#foreach (KeyValuePair<string, DriftStatus> status in (Dictionary<string, DriftStatus>)Session["statusDict"])
{
<div class="card">
<div class="card-body">
#status.Value.MailTitel
<div class="btn-group btn-group-justified">
#Html.ActionLink("Fortsæt", "ContinueStatus", "Home", new { status_id = status.Key }, new { #class = "btn btn-primary" })
#Html.ActionLink("Afslut", "EndStatus", "Home", new { #class = "btn btn-primary" })
</div>
</div>
</div>
}
</div>
Controller:
public ActionResult Submit(DriftStatus driftstatus) {
AddStatus(driftstatus);
ModelState.Clear();
return View("Index", new DriftStatus());
}
public ActionResult ContinueStatus(string status_id)
{
return View("Index",FindStatus(status_id));
}
private DriftStatus FindStatus(string key)
{
Dictionary<string, DriftStatus> statusDict = Check_statusDict();
DriftStatus driftstatus = statusDict[key];
if (driftstatus == null)
{
return new DriftStatus();
}
return statusDict[key];
}
private void AddStatus(DriftStatus driftstatus)
{
Dictionary<string, DriftStatus> statusDict = Check_statusDict();
if (!statusDict.ContainsKey(driftstatus.Created))
{
driftstatus.Created = DateTime.Now.ToString();
statusDict.Add(driftstatus.Created, driftstatus);
}
}

How can I refresh a partial view on the main index page on a submit from a separate partial view modal

I have a main index page that loads a partial view that contains a dropdownfor list. The selection of an item from the ddl populates controls in a separate partial view for display. Clicking Edit pops open a model with a Form of EditorFor controls bound to the model properties for the selected item. When the submit button for the modal is clicked. It posts back the form for updating to the database...at which point I want to basically refresh the partial view that contains the dropdownlist so that it reflects the changes is appropriate.
The code I have performs all the basic mechanics without issue EXCEPT for refreshing the partial view that contains the dropdownlistfor control. I could just do a redirecttoaction for the index page and refresh the entire page but I would prefer to only refresh the partial view. I can not figure out how to make this happen and am wondering if someone has a suggestion.
The code div code for the index page is:
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<br />
<div class="partialContent" data-url="/Database/GetDatabases">
#Html.Partial("_GetDatabases")
</div>
<br />
<div class="modal fade" id="modalEditDBInfo" role="application" aria-labelledby="modalEditDBInfoLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modalEditDBInfoContent" style="background-color:white; border-radius:10px; box-shadow:10px;">
#Html.Partial("_EditDatabaseInfo")
</div>
</div>
</div>
The code for the EditDatabase partial view
#model Hybridinator.WebUI.Models.DatabaseModel
<br />
<br />
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
<h4 class="modal-title" id="editModelTitle">Edit Database Info</h4>
</div>
#if(Model != null)
{
using (Html.BeginForm("EditDatabaseInfo", "Database", FormMethod.Post, new { #class = "modal-form" }))
{
<div class="modal-body">
#Html.HiddenFor(m => m.database_pk, new { htmlAttributes = new { #class = "form-control" } })
<div class="form-group">
<div id="databaselabel">#Html.LabelFor(m => m.database_name, "Database")</div>
<div id="databaseedit">#Html.EditorFor(m => m.database_name, new { htmlAttributes = new { #class = "form-control" } })</div>
</div>
<div class="form-group">
<div id="databaseserverlabel">#Html.LabelFor(m => m.database_server, "Database Server")</div>
<div id="databaseserveredit">#Html.EditorFor(m => m.database_server, new { htmlAttributes = new { #class = "form-control" } })</div>
</div>
</div>
<div class="form-group">
<div id="editsqltypelabel">#Html.LabelFor(m => m.sql_type_pk, "Sql Type")</div>
<div id="editsqltypeddl">#Html.DropDownListFor(m => m.sql_type_pk, Model.sqlTypes)</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button class="btn btn-inverse btn-primary" type="submit">Save</button>
</div>
}
}
The code for the GetDatabases partial view
#model Hybridinator.WebUI.Models.DatabaseListModel
#if(Model != null)
{
<div id="databasedropdown" class="container-fluid">
#Html.Label("Databases: ")#Html.DropDownListFor(m => m.database_pk, Model.databases, "Select one...", new { #id = "database_pk", onchange = "changeDatabase()" })
</div>
}
The Controller code for GetDatabases
public ActionResult GetDatabases()
{
DatabaseListModel databaseListModel = new DatabaseListModel
{
databases = databaseService.GetUndeletedDatabaseList().
Select(d => new SelectListItem
{
Value = d.database_pk.ToString(),
Text = d.database_name
}).ToList()
};
return PartialView("_GetDatabases",databaseListModel);
}
and last the code for both the Get and Post for the EditDatabase modal
[HttpGet]
public ActionResult EditDatabaseInfo(int database_pk)
{
DatabaseModel databaseModel = FillDatabaseModelByDatabasePK(database_pk);
return PartialView("_EditDatabaseInfo", databaseModel);
}
[HttpPost]
public ActionResult EditDatabaseInfo(DatabaseModel databaseModel)
{
string[] result = databaseService.Update(new Database
{
database_pk = databaseModel.database_pk,
database_name = databaseModel.database_name,
database_password = databaseModel.database_password,
database_username = databaseModel.database_username,
database_server = databaseModel.database_server,
hist_database_name = databaseModel.hist_database_name,
hist_database_server = databaseModel.hist_database_server,
hist_database_password = databaseModel.hist_database_password,
hist_database_username = databaseModel.hist_database_username,
sqlType = new SQLType { sql_type_pk = databaseModel.sql_type_pk }
});
return RedirectToAction("GetDatabases");
}
As I said the RedirectToAction("Index) returned in the Post EditDatabase controller method works in a pinch..but I really dont want to have to refresh the whole page. I assume there is something I can do differently in the return on that method to just reload the GetDatabases partial but I can't figure it out. Any help would be appreciated.
Carl who comments up above provided the solution. Buts since he just commented Ill post the code modifications here so if someone is looking for a similar issue they can see the code.
As per Carl's suggestion I used the Ajax.BeginForm rather than the HTML.BeginForm and IM updating the partial view controller through the onsuccess handler.
I replaced this line in the EditDatabase partial
using (Html.BeginForm("EditDatabaseInfo", "Database", FormMethod.Post, new { #class = "modal-form" }))
with this
using (Ajax.BeginForm("EditDatabaseInfo", "Database", new AjaxOptions{
InsertionMode = InsertionMode.Replace,
HttpMethod = "POST",
OnSuccess = "editDatabaseSuccess"
}, new { #id = "editDatabaseForm" }))
Then in my scripts I made a function for the editDatabaseSucess
<script type="text/javascript">
function editDatabaseSuccess(data)
{
//alert(data);
$('#modalEditDBInfo').modal('hide');
loadDatabases();
}
</script>
The alert(data; commented out line was just for testing to make sure the function was being called.
the loadDatabases(); line calls the function I use on page load to load the partial view.
<script type="text/javascript">
function loadDatabases()
{
$(".partialContent").each(function (index, item) {
var url = $(item).data("url");
if (url && url.length > 0) {
$(item).load(url)
}
});
}
</script>
Works perfectly now. Much thanks to Carl for the answer.

HTML.Partial() is not working when displaying it?

In Asp.net mvc 5. we have a login page which implements HTML.BeginForm() to post data to controller , if the username and password are incorrect, we are sending error back to the front end using partial views. Everything work fine, In case of error only error message is displayed on the screen and nothing else.
Controller
[HttpPost]
public ActionResult SingleSSOMPLogin(SSoStateModel model)
{
//Check the Code with SP providers and Authorization server.
if(model.SAMLAssertion.validMPData)
{
return RedirectToAction("SSOServiceMP" , "SAML");
}else
{
//Error message processed.
model.errorMessage = SSOState.SAMLAssertion.errorMessage;
return PartialView("_LoginError" , model);
}
}
The view contain the following Code
<div class="peripheral">
<div class="panel panel-default panel-peripheral">
#{Html.Partial("_LoginError", Model);}
<div class="panel-heading clearfix">Please Log In</div>
<div class="panel-body">
<div class="brand-logo eop-logo">
<script type="text/javascript">
function changeImage() {
document.getElementById("Logo").src = '#Url.Content("~/Content/images/TopLogo.gif")';
}
</script>
<img id="Logo" width="200" src='#Url.Content("~/Content/images/TopLogo.gif")' onerror="changeImage()" />
#{ Html.EnableClientValidation(true);}
<!--Ajax call to Controller-->
#using (Html.BeginForm("SingleSSOMPLogin", "Accounts"))
{
#Html.ValidationSummary(true);
<div id="group-email" class="form-group col-md-12 ">
#Html.TextBoxFor(m => m.Email, new { #class = "form-control", placeholder = "Please enter your Email address" })
#Html.ValidationMessageFor(m => m.Email)
</div>
<div id="group-password" class="form-group col-md-12">
#Html.PasswordFor(m => m.Password, new { #class = "form-control", placeholder = "Please enter your password" })
#Html.ValidationMessageFor(m => m.Password)
</div>
<div class="form-group">
<div class="col-md-12">
<button type="submit" class="btn btn-primary pull-left">Login</button>
<a id="forgot" href='#Url.Action("ForgotPassword","Accounts")' class="btn btn-link btn-sm pull-right">Forgot your password?</a>
</div>
</div>
}
</div>
</div>
</div>
</div>
Partial View
#{
Layout = null;
}
#if (Model.Result!= null)
{
<div class="alert alert-warning alert-dismissable">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
<strong>#Model.Result.errorMessage</strong>
</div>
}
When Error occur, I get redirect to same view again with all query parameter gone and display only error message.
How to solve following issue?
The partial view will return only the fragment you defined.
So when called from a "complete" view with
#{Html.Partial("_LoginError", Model);}
it will generate the corresponding part of the view.
In your situation what is most common is to add a model error and return the complete view (that must have a ValidationSummary section):
[HttpPost]
public ActionResult SingleSSOMPLogin(SSoStateModel model)
{
//Check the Code with SP providers and Authorization server.
if(model.SAMLAssertion.validMPData)
{
return RedirectToAction("SSOServiceMP" , "SAML");
}else
{
//Error message processed.
ModelState.AddModelError("error", SSOState.SAMLAssertion.errorMessage);
return View(model);
}
}
If you want to use the partial view you have to call it from an javacript ajax call and insert the response in your page. With jQuery it is something more or less like:
$.ajax({ url: <partial view url>,
type: 'GET',
success: function (result) {
$(updateSelector).hide().html(result).effect("fade", "fast");
}
});

Enable textboxes and button after form submittal ASP.NET MVC 4

I would like to enable the update button after form submittal. Here's my code:
VIEW:
#using (Html.BeginForm("ProcessTech", "Home", FormMethod.Post))
{
#Html.TextBoxFor(m => m.techNo, new { #class = "form-control maintain-text", placeholder = "Technician No..." })
<span class="input-group-btn">
<button type="submit" id="search" name="SubmitButton" value="search" class="btn btn-default">
<i class="fa fa-search"></i>
</button>
</span>
<td>First Name :</td>
<td class="display-field">#Html.TextBoxFor(m => m.firstName, new { #class = "form-control", style = "width:380px;", disabled = "disabled" })</td>
<td>Last Name :</td>
<td class="display-field">#Html.TextBoxFor(m => m.lastName, new { #class = "form-control", style = "width:380px;", disabled = "disabled" })</td>
<button name="SubmitButton" value="update" id="update" type="submit" style = "float:right;margin-right:10px; border-radius:5px;" class="btn btn-default" disabled><i class='fa fa-edit fa-fw'></i>Update</button>
}
The update button, firstname & lastname textboxes has a 'disabled' attribute.
After searching the technician number, the form will be updated with the firstname & lastname values that corresponds to the tech number.
Now I want to remove the disabled attribute of the update button, firstname and lastname so that it can be edited and updated. What's the best way to do this?
I tried this:
SCRIPT:
$(document).ready(function () {
$("#search").click(function () {
$("#update,#firstName,#lastName").removeAttr("disabled");
});
});
It enables the elements while the form is submitting but as soon as the form is submitted the page reloads with the values already in the textboxes and disables back the elements.
When you post the form to the controller you can return a value in the model to the view, which will determine if the button will be disabled or enabled, or you can also use #Viewbag.disableUpdate so that after post the button renders correctly
<button name="SubmitButton" value="update" id="update" type="submit" class="btn btn-default" #ViewBag.disableUpdate ><i class='fa fa-edit fa-fw'></i>Update</button>
From the controller pass #ViewBag.disableUpdate="" // to make it enable
and #ViewBag.disableUpdate="disable"; // to make it enabled
I've modified my code based on Maneesh's answer and here's what I've come up:
MODEL:
public bool setEnable { get; set; }
public IndexModel() { setEnable = false; } //constructor
CONTROLLER:
public ActionResult Index()
{
return View(new IndexModel());
}
[HttpPost]
public ActionResult ProcessTech(string SubmitButton)
{
IndexModel _oTechModel = new IndexModel();
switch (SubmitButton)
{
case "search": //search technician
{
_oTechModel.setEnable = true;
}
break;
}
return View("Index", _oTechModel);
}
VIEW:
#model Maintenance_.Models.IndexModel
#{
ViewBag.Title = "Technician";
if(Model.setEnable==true)
{
ViewBag.disableUpdate = "";
}
else{
ViewBag.disableUpdate = "disabled";
}
}
//HTML codes goes here..

Categories

Resources