I have an MVC application that when a link is clicked a page needs to be displayed based on the same values on another page. I can't figure out why what's getting passed is null instead of the string. My code is below.
Controller:
public string searchQ
{
get { return (string)Session["searchQ"]; }
set { Session["searchQ"] = value; }
}
public ActionResult Index()
{
Session["InitialLoad"] = "Yes";
return View();
}
[HttpPost]
public ActionResult Index(string heatSearch)
{
ViewBag.SearchKey = heatSearch;
searchQ = heatSearch;
return View();
}
public ActionResult Index_Perm()
{
ViewBag.SearchKey = searchQ;
return View();
}
public ActionResult PartialMainLim(string heatSearch)
{
HomeModel C = new HomeModel();
ChemViewModel D = new ChemViewModel();
D = C.QueryResults(heatSearch);
return PartialView(D);
}
public ActionResult PartialMain(string heatSearch)
{
HomeModel C = new HomeModel();
ChemViewModel D = new ChemViewModel();
D = C.QueryResults(heatSearch);
return PartialView(D);
}
The code in the index view looks like this (this one works):
#if (ViewBag.SearchKey != null)
{
<div>
#Html.Action("PartialMainLim", "Home", (string)ViewBag.SearchKey)
</div>
}
And in the index_perm view:
#if(ViewBag.SearchKey != null)
{
<div>
#Html.Action("PartialMain", "Home", (string)ViewBag.SearchKey)
</div>
}
When I check the value of SearchKey in both views it is correct. However for the method "PartialMain" null gets passed instead of the string, despite SearchKey being correct. This all works for the other view though. What am I doing wrong?
When passing values back to controller you have basically two options:
Make a form
Pass it as part of the url
Get methods only accept url attributes while Post methods are able to handle form content as well.
From what you are trying to do I'd say you could use something like:
#Html.Action("PartialMain", "Home", new {heatSearch = (string)ViewBag.SearchKey})
this should create url looking like /Home/PartialMain?heatSearch=[content of SearchKey]
EDIT:
That will only pass the value given it is present in the ViewBag. You are getting it from the Session which is imho a terrible idea in MVC (which should be session-less). Please consider if you really need it there. Usually there are other ways to implement this.
There is no HttpPost handler in the controller when you click the index_perm view.
I think that problem is your session that would be null. One of principles of framework ASP.NET MVC is stateless. Using session in ASP.NET MVC quite horrible.
At the moment, I think you can quickly fixed it by using TempData that default using Session under the hood. You could have a look an outdated article for further digging up ViewData vs TempData
Related
I need to display a value in an editable textbox on my mvc page when it first loads if it exists. I've got a function that will take care of getting the value that I need, but I need to pass in parameters from the current model to get what I need from the database.
The problem I'm having is getting this value into the textbox. What I tried was
cshtml:
#Html.TextBoxFor(model => model.AdjustedLiabilityAmount, new { #Value=OBS_LIB.BLL.JeopardyAssessment.JeopardyAssessment.GetLatestAdjustedLiabilityAmount(Model.DOTNumber, Model.LiabilityAmount))}
I get a red squiggly that "The name 'Value' does not exist in the current context"
So I tried a different technique I read about which was like this.
Controller:
public ActionResult Index()
{
ViewBag.AdjustedValue = OBS_LIB.BLL.JeopardyAssessment.JeopardyAssessment.GetLatestAdjustedLiabilityAmount(Model.DOTNumber, Model.LiabilityAmount);
cshtml:
#Html.TextBoxFor(model => model.AdjustedLiabilityAmount, new { #Value=ViewBag.AdjustedValue)}
This time I'm getting the red squiggly "The name 'Model' does not exist in the current context."
I'm sure I'm just missing something basic here as I'm new to MVC.
Any help is much appreciated.
Entire ActionResult Index:
public ActionResult Index()
{
ViewBag.AdjustedValue = OBS_LIB.BLL.JeopardyAssessment.JeopardyAssessment.GetLatestAdjustedLiabilityAmount(Model.DOTNumber, Model.LiabilityAmount);
var Report = new OBS_LIB.DTO.JeopardyAssessmentReport();
Report.Stage = 1;
Report.Status = "Active";
Report.ReportItems = OBS_LIB.BLL.JeopardyAssessment.JeopardyAssessment.GetJAReportItems(Report.Stage, Report.Status);
return View(Report);
}
You want to do something like this:
Class:
public class ModelClassHere {
public float Liability {get;set;}
}
Controller:
public ActionResult Index(ModelClassHere model) {
model.Liability = 10.00;
return View(model); // pass model to the view
}
View:
#Html.TextBoxFor(x => x.Liability) // 'x' can be anything
EDIT*
If you already have a model and need to pass one simple value:
Controller:
public ActionResult Index(ModelClassHere model, string otherValue) {
model.Liability = 10.00;
ViewBag.Liability = model.Liability;
return View(model); // pass model to the view
}
View:
<input type="text" id="otherValue" name="otherValue" value="#ViewBag.Liability.ToString()" />
You can use
#Html.TextBox("AdjustedLiabilityAmount", (Decimal)ViewBag.AdjustedValue)}
Or
#Html.TextBox("AdjustedLiabilityAmount", Model.AdjustedLiabilityAmount == null ? (Decimal)ViewBag.AdjustedValue : Model.AdjustedLiabilityAmount)}
In decimal type you put your the type that you need.
You need to pass your model in the
Controller
return view(myModelName);
make sure you have access to it in your controller.
also your view has to reference the model in the #model line at the top.
Finally to call the model it would be
view:
Model.myModelName
How can I send DropDownList's SelectedValue to the Controller from View with BeginForm?
Here's my code:
#using (Html.BeginForm(new { newvalue=ddl.SelectedValue}))
{
#Html.DropDownList("categories",
(List<SelectListItem>)ViewData["categories"],
new { onchange = "this.form.submit()", id = "ddl" })
Do not use ViewData or ViewBag in place of your model. It's sloppy, prone to error and just an unorganized way of giving your view data.
{ newvalue=ddl.SelectedValue} is going to do nothing for you when placed on the form itself. You need to understand that everything you're writing is evaulated on the server before being sent down the client. So if newvalue resolves to 1 it will continue to stay 1 forever unless you have javascript that changes it on the clientside (which you're not doing and you shouldn't be doing).
First you need a model:
public class CategoryModel()
{
public IEnumberable<SelectListItem> CategoriesList {get;set;}
public int SelectedCategoryId {get;set;}
}
Controller
public class CategoryController()
{
public ActionResult Index()
{
var model = new CategoryModel();
model.CategoriesList = new List<SelectListItem>{...};
return View(model);
}
public ActionResult SaveCategory(CategoryModel model)
{
model.SelectedCategoryId
...
}
}
View
#model CategoryModel
#using(Html.BeginForm("SaveCategory","Category"))
{
#Html.DropDownListFor(x=> x.SelectedCategoryId, Model.CategoriesList)
<button type="submit">Submit</button>
}
What's happening here is SelectList is being populated from the IEnumerable and it's form name is SelectedCategoryId, that's what is posed back to the server.
I'm not sure where your knowledge of http and html ends, but you should not be using any framework until you understand how http and html work and then what these helpers such as begin form and Html.DropDownList are actually doing for you. Understand how the screw works before you try to use the screw driver.
My problem is that I am trying to setup a drop down list and when a new item is selected it will update a table of information that I have but every time HttpPost function gets called the parameter is always null. Here is index function of my home controller:
public ActionResult Index()
{
Project[] projects = db.Projects.ToArray();
List<SelectListItem> dropList = new List<SelectListItem>();
BurndownSprintTable[] TableToShow = db.BurndownSprintTables.ToArray();
for (int index = 0; index < projects.Length; ++index)
{
dropList.Add(new SelectListItem { Text = projects[index].Name, Value = projects[index].Id.ToString(), Selected = projects[index].Selected });
if (projects[index].Selected == true)
{
int ProjectId = projects[index].Id;
TableToShow = db.BurndownSprintTables.Where(x => x.ProjectId == ProjectId).ToArray();
}
}
ViewBag.Projects = dropList;
return View(TableToShow);
}
TableToShow is used to show sprint information per project.
Here is the post function:
[HttpPost]
public ActionResult ProjectUpdate(string strProjectId)
{
return View("Index");
}
I realize this post function will cause an error which I believe I can fix on my own but I need strProjectId to not be null.
Here is the html:
#model IEnumerable<TableauConfigWebService.Models.BurndownSprintTable>
#using (Html.BeginForm("ProjectUpdate", "Home", FormMethod.Post))
{
<h5>#Html.DropDownList("Id", (IEnumerable<SelectListItem>)ViewBag.Projects)
<input type="submit" value="Update" /></h5>
}
There is more to it but the rest of the html is setting up a table for the sprint information which works fine.
I have looked around and found a bunch of posts on this but none of them seem to help. I am new to mvc so I know its probably something simple but I cant figure it out.
Thank you for any help.
Change to this
[HttpPost]
public ActionResult ProjectUpdate(string Id)
{
return View("Index");
}
Or change the control Name to
#Html.DropDownList("strProjectId", (IEnumerable<SelectListItem>)ViewBag.Projects)
Try this simple way , and check it ,
Must be same names are dropdown and model property .
But you can try this simple way
[HttpPost]
public ActionResult ProjectUpdate()
{
**string strProjectId=Request.Form["strProjectId"].ToString();**//Or use Request["strProjectId"].ToString();
return View("Index");
}
#Html.DropDownList("**strProjectId**", (IEnumerable<SelectListItem>)ViewBag.Projects)
or
Simply, you can use FormCollection like,
[HttpPost]
public ActionResult ProjectUpdate(FormCollection collection)
{
**string strProjectId=collection["strProjectId"].ToString();**
return View("Index");
}
#Html.DropDownList("**strProjectId**", (IEnumerable<SelectListItem>)ViewBag.Projects)
And check my code with using break points !
Use the same parametre name at both the place in view and controller.
either change in controller.
public ActionResult ProjectUpdate(string Id)
{
return View("Index");
}
or else change in view dropdown code to this.
#Html.DropDownList("strProjectId", (IEnumerable<SelectListItem>)ViewBag.Projects)
hope this helps...
So I got this webproject i'm working on, and in 4/5 views Im using
#Html.ActionLink("Back to List", "Index", new { id=Model.ClientID})
All of the views return me to my list exept my "Create New View"
This will also be the only view not to load, giving me the exeption of "System.NullReferenceException"
I'm confused on why this is the only view that won't let me pass a clientID to it ( since i need not only it but also the CountyID to create a new County, And more so telling me that it is null.
If i remove the line of code above my code runs fine ( exept adding my 2 ID fields into the create view obviously ) wich made me think it may be my controller.
Here is my action from givin controller for create
// GET: /County/Create
public ActionResult Create()
{
return View();
}
for comparison here is an edit action in the same controller
public ActionResult Edit(int id = 0)
{
dbCounty countys = db.Countys.Find(id);
if (countys == null)
{
return HttpNotFound();
}
return View(countys);
}
I've also tryed adding this code to the create new actionlink wich is when i get this error
HTTP Error 404.0 - Not Found
The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.
Most likely causes:
The directory or file specified does not exist on the Web server.
The URL contains a typographical error.
A custom filter or module, such as URLScan, restricts access to the file.
What am i doing wrong here ....
My project is build on a hierachy model, One Client Many Countys ( if you need more code let me know )
thanks in advance.
Tip:
there must be a reason ( my assumption ) why when removing this line of code it works ( so it must be this line of code ?? ) - must be a different way of passing it ( clientID does have a value of 1 )
#Html.ActionLink("Back to List", "Index", new { id=Model.ClientID})
Edit Index Controller needed :
public ActionResult Index([Bind(Prefix="id")] int CID=0)
{
var clnt = db.Clients.Find(CID);
if (clnt != null)
{
return View(clnt);
}
return HttpNotFound();
}
EDIT: new create action from Countys Controller
public ActionResult Create(int id=0)
{
dbCounty countys = db.Countys.Find(id);
if (countys == null)
{
return HttpNotFound();
}
return View(countys);
}
i have also tryed running
public ActionResult Create(int id=0)
{
dbClient Client = db.Clients.Find(id);
if (Client == null)
{
return HttpNotFound();
}
return View(Client);
}
( since i am passing a clientID - the way the models are built it should add a county id while creating this new row in the database with the clientID(passedVariable)
You don't seem to be passing a model to the Create view. In your Create controller, you need something like the following, where Client is an object that has the property ClientID.
public ActionResult Create()
{
...
return View(Client);
}
EDIT:
To clarify, in your Create View, the Model is null, because you didn't pass it one in the controller. Take a look at the controllers that work, and see what it's passing to the View. You'll need to do something similar for Create.
I will try to sum up your problem. You said that if you remove
#Html.ActionLink("Back to List", "Index", new { id=Model.ClientID})
There is no errror, and the error happens when your view is generating. This two facts means that in 99% your Model is null
Check that in
#Html.ActionLink("Back to List", "Index", new { id=Model.ClientID})
Model is not null, otherwise you will get null reference exception
I have an HttpPost and HttpGet version of the action method Rate() :
http://pastebin.com/embed_js.php?i=6x0kTdK0
public ActionResult Rate(User user, Classified classified)
{
var model = new RatingModel
{
CurrentUser = user,
RatedClassified = classified,
};
return View(model);
}
[HttpPost]
public ActionResult Rate(RatingModel model)
{
model.RatedClassified.AddRating(model.CurrentUser, model.Rating);
return RedirectToAction("List");
}
The view that HttpGet Rate() returns:
#model WebUI.Models.RatingModel
#{
ViewBag.Title = "Rate";
}
Rate #Model.RatedClassified.Title
#using(Html.BeginForm("Rate","Classified", FormMethod.Post))
{
for (int i = 1; i < 6; i++)
{
Model.Rating = i;
<input type="submit" value="#i" model="#Model"></input>
}
}
I'm trying to find out to send a Model through the Form to the Post method, and my thinking was that the value "model" in the submit button's tag would be the parameter to do so, however null is being passed through if i breakpoint inside of the Post method. The for loop is trying to create 5 buttons to send the proper rating.
Thanks
Them model binding works on the name attribute as #Ragesh suggested you need to specify the name attributes matching the RatingModel properties in the view. Also note that the submit button values dont get posted to the server, there are hacks through which you can achieve that, one way is to include a hidden field.
Also in your provided code the loop runs six times and at the end Model.Rating will be equal to 5 always... what are you trying to achieve?. Say for example you have a model like
public class MyRating{
public string foo{get;set;}
}
in your view
#using(Html.BeginForm("Rate","Classified", FormMethod.Post))
#Html.TextBoxFor(x=>x.foo) //use html helpers to render the markup
<input type="submit" value="Submit"/>
}
now your controller will look like
[HttpPost]
public ActionResult Rate(MyRating model)
{
model.foo // will have what ever you supplied in the view
//return RedirectToAction("List");
}
hope you will get the idea
I think there are two things you need to fix:
The input tag needs a name attribute
The name attribute should be set to model.Rating