can't pass multiple parameters using mvc4 html.beginform(...) - asp.net-mvc-4

In my mvc4 application i want to use html.beginform() to pass multiple parameters to an actionResult on the same controller.
I do it like this:
view:
<div>
#using (Html.BeginForm("AddNote", "Lead",FormMethod.Post, null))
{
#Html.Hidden("leadID",#Model.ID)
<input type="text" name="noteBody" />
<input type="submit" class="mainButton" value="Add New!"/>
}
</div>
Controller (LeadController):
[HttpPost]
ActionResult AddNote(int leadID, string noteBody)
{
Note note = new Note();
note.DateModified = DateTime.Now;
note.Title = "No Title";
note.Body = noteBody;
Lead lead = unitOfWork.LeadRepository.GetById(leadID);
lead.Notes.Add(note);
unitOfWork.Save();
return RedirectToAction("Details", new { id = leadID });
}
when i press the submit button i get an exception:
The resource cannot be found.
Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
Requested URL: /Lead/AddNote
this is the place to say that i have tried it withput parameters and it worked just fine.
I've also tried to pass the "leadID" parameter inside the form declaration (new {leadID = #Model.ID}).
Any idea what am i doing wrong ?

Just add the 'public' modifier to your action and it will do the magic.

The AddNote method should be public. Use the public keyword and it will work.

Add the HTTPPOST attribute , like this
[HttpPost]
ActionResult AddNote(int leadID, string noteBody)
{
Note note = new Note();
note.DateModified = DateTime.Now;
note.Title = "No Title";
note.Body = noteBody;
Lead lead = unitOfWork.LeadRepository.GetById(leadID);
lead.Notes.Add(note);
unitOfWork.Save();
return RedirectToAction("Details", new { id = leadID });
}
Perhaps it helps you

Related

Select dropdown value after post

I was hoping for some guidance on an issue I am having with preserving the value in a dropdownlist after post (razor)
I have a simple page:
#model testContingency.Models.ListByWardDD
#{
ViewBag.Title = "TestDropDowns";
}
<h2>TestDropDowns</h2>
<div>
#Html.DropDownList("HospModel", Model.Hospital, new { #onchange = "ChangeHospital(this.value)" })
#Html.DropDownList("WardModel", Model.Wards)
<script type="text/javascript">
function ChangeHospital(val) {
window.location.href = "/PatientListByWardDD/TestDropDowns?hospID=" + val;
}
</script>
</div>
here's the controller
public ActionResult TestDropDowns(int? hospID)
{
PASInpatientRepository pasRepo = new PASInpatientRepository();
var returnModel = new ListByWardDD();
var HospitalData = pasRepo.GetPatientHospitalsEnum();
returnModel.Hospital = pasRepo.GetHopspitalListItems(HospitalData);
var WardData = pasRepo .GetPatientWardsEnum(hospID);
returnModel.Wards = pasRepo.GetWardListItems(WardData);
ViewBag.HospSearch = hospID;
return View(returnModel);
}
In the controller PASInpatientRepository() communicates with a cache database. It passes back public IEnumerable < SelectListItem > GetHopspitalListItems. It calls stored procedures written within a cache database (same as sql stored procedures in essence). This is all working fine in its own crude way.
The issue I am having is that when I select the dropdownlist #Html.DropDownList("HospModel", Model.Hospital, new { #onchange = "ChangeHospital(this.value)" }) and the controller is called to refresh the Wards dropdown, I want to preserve the value I have selected in the hospital dropdown. I have tried a few different ways, but I admit, I'm a bit stuck. Most examples I found are for strongly typed.
As I mentioned, I'm new to MVC, but any advice on how to solve this issue, or suggestions on improving my code are greatly appreciated.
So I'm not sure what the Hospital property looks like but I'll make the assumption that each one has a unique ID.
Furthermore to bind the posted data to the view model you'll need to use forms in your view. To create the drop down list use the DropDownListFor-Helper. This way the data will be bound back to your Model after submitting the form.
So your view could look something like this
#model testContingency.Models.ListByWardDD
#{
ViewBag.Title = "TestDropDowns";
}
<h2>TestDropDowns</h2>
<div>
#using (Html.BeginForm("TestDropDowns", "YourController", FormMethod.Post))
{
#Html.DropDownListFor(x => x.HospitalID, Model.Hospital)
#Html.DropDownListFor(x => x.WardID, Model.Wards)
<input type="submit" value="send" />
}
</div>
Your ViewModel testContigency.Models.ListByWardDD must have at least the following properties
public class ListByWardDD {
public int HostpitalID { get;set; }
// the value of the SelectListItem-objects should be the hospital ID
public IEnumerable<SelectListItem> Hospital { get;set; }
public int WardID { get;set; }
// the value of the SelectListItem-objects should be the ward ID
public IEnumerable<SelectListItem> Wards { get;set; }
}
Once you post the form (for simplicity I added a button to send the form and left the javascript part out) the method TestDropDowns of your controller (which you need to fill in the BeginForm-Helper) will be called. That method expects expects an object of type ListByWardDD as a parameter and the framework will automatically populate the values for you.
[HttpPost]
public ActionResult TestDropDowns(ListByWardDD viewModel) {
// your code here, viewModel.HospitalID should contain the selected value
}
Note: After submitting the form the properties Hospital and Wards will be empty. If you need to display the form again, you need to repopulate those properties. Otherwise your dropdown lists are empty.
I tried my best to post valid code but I did not compile or test it.

There is no ViewData item of type 'IEnumerable<SelectListItem>' that has the key 'BranchQuickChange'

I've been on this error for a while and the ienumerable object is blocking can someone pls help me the error is in the description.
HTML:
#model IEnumerable<DatabaseDAL.Models.WAGTripHdr>
<script type="text/javascript" src="~/Scripts/jquery-1.9.1.min.js"></script>
<script type="text/javascript">
$("select#BranchQuickChange").change(function () {
var branchName = $("select#BranchQuickChange option:selected").text();
alert(branchName);
window.location.href = '#Url.Action("QuickBranchChange", "TripSheets")?branchName=' + branchName;
});
</script>
<div class="row-fluid">
<div class="span4" style="margin-top: 15px">
#if (User.IsInRole("Administrator") || User.IsInRole("SuperUser"))
{
<strong>Quick Switch</strong> #Html.DropDownList("BranchQuickChange",ViewBag.CompanyList as SelectList)
}
</div>
Controller:
{
List<WAGBranch> listWagBranch = WAGBranchRepository.GetAllBranches(CompanyEnum.WAG).OrderBy(i => i.BRName).ToList();
List<string> listCompany = new List<string>();
foreach (WAGBranch branch in listWagBranch)
{
listCompany.Add(branch.BRName); // + " - " + branch.Branch);
}
//listCompany.Insert(0, "WAG HEAD OFFICE - WAG");
if ((string)selected == "") selected = null;
ViewBag.CompanyList = new SelectList(listCompany, selected);
}
Model:
[TableNameAttribute("WAGTripHdr")]
public class WAGTripHdr : SQLSelectUpdateInsertHelper
{
public string DebName { get; set; }
}
Waiting for some advices.
That error usually occurs when the collection passed to DropDownListFor is null. As a fallback, the helper tries to find the options in the ViewBag under a member named after the property, i.e. ViewBag.BranchQuickChange. When it fails to find anything usable there, as well, it gives up and you get the exception you reference.
That said, it appears you are in fact setting ViewBag.CompanyList in your action. Additionally, it is being set to a SelectList instance, so casting it back to SelectList in the view as you're doing should materialize the value. The only thing I can think of is that perhaps a different action than the one you've posted here is being loaded. In particular, if you have GET and POST versions of this action, make sure that both set ViewBag.CompanyList. It's possible you only added that line to one and not the other.

Post back Errors in MVC 4

In regular Asp.Net, when you want to post an error, for ex, a duplicate ID, I use Panels for controls, error message labels, etc. I was wondering, how to achieve the same using MVC 4.
Currently, on my Index page, I have an Id, Name & Address column and a Submit button. My HTTPPOST ActionResult here:
[HttpPost]
public ActionResult Index(Person p)
{
if (ModelState.IsValid)
{
PersonInfo pi = new PersonInfo();
var duplicate = from d in db.PersonInfoes
where d.Id == p.Id
select d;
if (duplicate.Any())
{
return View("Duplicate");
}
else
{....}
When I enter a duplicate Id, upon submitting the page, I need to post to the same view ("Index") page to let user know that there is an Id already, but currently, I am redirecting to a different view to let user know as a duplicate, and I dont think this is the right way to do this. I am learning MVC, btw and hence this doubt. My duplicate cshtml here:
#{
ViewBag.Title = "Duplicate";
}
<h2>Duplicate</h2>
<h3>Duplicate ID found !!</h3>
<p>Please correct the ID and re-enter !</p>
<br/><br/>
#Html.ActionLink("Back to Data Entry","Index")
Any pointers would help.
You can return to the same view. You should consider adding an error to the model state dictionary so that you can show that in the UI.
[HttpPost]
public ActionResult Index(Person p)
{
if (ModelState.IsValid)
{
var duplicate= db.PersonInfoes.Where(s=>s.Id== p.Id);
if (duplicate.Any())
{
ModelState.AddModelError(string.Empty,"Duplicate found");
return View(p);
}
// to do : Your existing code
}
return View(p);
}
Just make sure you are calling the ValidationSummary method in your Index view to show this error message.
#model Person
#using (Html.BeginForm())
{
#Html.ValidationSummary(false)
<!-- Your form fields goes here-->
<input type="submit" />
}

Passing textbox value from View to action without using Html.begin form and Submit button

I have created a texbox. When user give some input in the textbox and click the actionlink below, the value of the textbox will get pass to the actionResult(FWMenu) in the controller. I can not use html.begin form and submit button in the view. And i can not even use [httppost] in my controller.
Is it possible in that way? If yes then please help me how.
I have not used any class in model.
Below is my Controller.
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult FWMenu(string username)
{
return View();
}
}
This is my View.
<div>
#Html.TextBox("txtUserName")
#Html.ActionLink("Login", "FWMenu", new { username = #Html.TextBox("txtUserName") })
</div>
You need to use javascript/jquery to build the url and redirect. From your comments you mentioned you wanted to use a image rather than a button or link, and that you will have multiple items, so assuming you html is
<div>
<input type="text" name="username">
<img class="submit scr=....>
<div>
<script>
var urlBase='#Url.Action("FWMenu");
$('.submit').click(function() {
var userName = $(this).prev('input').val();
location.href = urlBase + '/' + userName;
}
</script>
Side note: No real point using #Html.TextBox("txtUserName") and if you have multiple instance of this it would generate invalid html (duplicate id attributes) and in any case the name of the parameter is username so it would have needed to be #Html.TextBox("username")`

How to Set value for Hidden field in Razr MVC

In my application I need to pass some values from one page(page A to Page B) to another page.
For this I am using Session variables(I cannot use Tempdata as it doesn't work on loadbalancing).
In Page A I am setting the Session Variable.
In Page B I need to retrieve the above Session variable.
For this I am using a Hidden field in Page B.
I dont know how to set the Session Variable to Hidden Field in Page B.
Page A
[HttpPost]
public JsonResult GetFileName(string updatedfileName, string orgfileName)
{
Session["OrgFileName"] = orgfileName;
Session["UpdatedFileName"] = updatedfileName;
var result = myService.getFile(updatedfileName, orgfileName);
return Json(result, JsonRequestBehavior.AllowGet);
}
Page B
<div style="display:none" >
<input type="hidden" value="" id="hdnfilename" />
</div>
In the controller of "Page B", set a ViewBag.MyValueto your session variable and apply it to the hidden's value.
Controller
ViewBag.MyValue = Session["MYVALUE"];
View
<input type="hidden" value="#ViewBag.MyValue" id="hdnfilename" />
If you need to get a session variable from JavaScript, you will need to develop an action that will return the session variable and consume it with JavaScript/jQuery, like this:
// Controller code
[HttpGet]
public JsonResult GetSessionVarValue(string key)
{
return Json(new { key = key, value = Session[key] }, JsonRequestBehavior.AllowGet);
}
// JavaScript code
var mySessionValue;
$.getJSON("/GetSessionVarValue", "MYKEY", function(data) {
mySessionValue = data.value;
});
You may take care with Session variables in load balance, too. The best way to secure store session variables is changing the state of session mode configuration to StateServer. http://msdn.microsoft.com/en-us/library/ms178586.aspx