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
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
I have a Model that I send to the view in a GET method and is bounded successfully to TextFor and ListFor's
e.g.
#Html.ListBoxFor(x => x.MultiChoice, new MultiSelectList(Model.property, "Id", "Name"), new { multiple = "multiple", #class = "multiselect" })
When the user submits the form, the Model is successfully passed back to the POST action method with its properties.
[HttpPost]
public ActionResult POST(Model quiz)
{
string Q1 = quiz.Q1 // = will equal what the user has put in. good
return View("Quiz", quiz);
}
However, when the Model (quiz) is returned to the view, the properties inside the quiz model are NULL, how do I retain the properties that come through to the POST method?
** Edit **
The GET Method
[HttpGet]
public ActionResult Quiz()
{
try
{
Quiz quiz = new Quiz();
// Of course, I could do this in the constructor of the model..
InitialiseQuiz(Quiz);
return View("Quiz", quiz");
}
catch (Exception ex)
{
}
}
Thanks
If I understood well, when you do this:
#Html.ListBoxFor(x => x.MultiChoice, new MultiSelectList(Model.property, "Id", "Name"))
the Razor will create a <select> tag with x.MultiChoice values as selected options. BUT, nowhere will be persisted the Model.property values (as it may be a collection, right?).
So, when you do the POST, you will only send the x.MultiChoice value back to the server, and the Model.property collection will be missed.
Knowing that, you just need to fill this property with the collection again during the POST action, like:
[HttpPost]
public ActionResult POST(Model quiz)
{
// some code here
quiz.property = new CollectionOfSomething();
return View("Quiz", quiz);
}
Is that what you are looking for?
The modelbinder news up an instance of that class with whatever POST data it has. Anything that's null has no posted data. The easiest way to make it not be null, then, is to create an HTML input for that property so that something is posted for it.
However, in situations where you're dealing with existing data, it's preferable to only post what you need to post, and then lookup the original object again in order to map the original property values back onto the version that was passed into your action:
[HttpPost]
public ActionResult Quiz(int id, Quiz model)
{
var quiz = db.Quizzes.Find(id);
// assuming `Foo` was a property that was not posted
model.Foo = quiz.Foo
...
}
My URL is something like,
localhost:19876/PatientVisitDetail/Create?PatientId=1
I have to retrieve the PatientId from the URL and pass it along the request.
I tried,
Url.RequestContext.Values["PatientId"] => System.Web.Routing.RequestContext does not contain a definition for 'Values' and
no extension method 'Values' accepting a first argument of type 'System.Web.Routing.RequestContext'
Again I tried,
RouteData.Values["PatientId"] => an object reference is required for the non static field, method
or property 'System.Web.Routing.RouteData.Values.get'
EDIT:
Based on the Jason's comment below, I tried Request["SomeParameter"] and it worked. But, there is also a warning to avoid that.
Any ideas how to avoid this for my scenario ?
My scenario:
There is a Create action method in my controller for creating a new patient.
But, I need to go back to the last page,
If I give something like,
#Html.ActionLink("Back to List", "Index")
=> this wont work because my controller action method has the following signature,
public ActionResult Index(int patientId = 0)
So, I must pass along the patientId in this case.
You are effectively circumventing the whole point of MVC here. Have an action which accepts PatientId i.e.
public ActionResult Create(int patientId)
{
return View(patientId);
}
Then in your view use that value e.g.
#model int
#Html.ActionLink("Back", "LastAction", "LastController", new { patientId = #Model })
This is the MVC way.
From your controller, you could put the PatientId in a ViewBag and access it from your View
public ActionResult Create()
{
ViewBag.PatientId = 1;
return View();
}
View
Html.ActionLink("Back", "Index", new { PatiendId = ViewBag.PatientId })
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
I have not changed my code, which used to work, I even clarified this with an earlier build of the project. However, I now get this error:
The parameters dictionary contains a null entry for parameter 'recipeID' of non-nullable type 'System.Int32' for method 'System.Web.Mvc.ActionResult Create(Int32, BareCupboard.Models.RecipeStep)' in 'BareCupboard.Controllers.RecipeStepController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter.
Parameter name: parameters
My code is:
[HttpPost]
public ActionResult Create(int recipeID, RecipeStep newRecipeStep)
{
try
{
var recipe = db.Recipes.Single(r => r.recipeID == recipeID);
recipe.RecipieSteps.Add(newRecipeStep);
db.SaveChanges();
return RedirectToAction("Index", "Recipe");
}
catch
{
return View();
}
}
I tried: int? recipeID, but this fails to work.
Any ideas what might have happened as all I can see is mysticism at play here!
Check your view code for the order of the parameters. The model binder needs it come in proper order. It is very easy to make mistake there.
Update
Here one way of resolving this. Create a view model as below:
public class RecipeViewModel
{
public int RecipeId { get; set; }
public RecipeStep RecipeStep { get; set; }
}
In the controller you will have the following:
public ActionResult Create()
{
var recipeId = 10 // however you want to select that Id
var recipeViewModel = new RecipeViewModel {RecipeId = 10}
return View(recipeViewModel);
}
[HttpPost]
public ActionResult Create(int recipeID, RecipeStep newRecipeStep)
{
//your code
}
In the view you can do the following:
#model MvcApplication3.Models.RecipeViewModel
#using (Html.BeginForm(null,null,FormMethod.Post))
{
<div>
<p>#Html.HiddenFor(x=>x.RecipeId) </p>
<p>#Html.TextBox("RecipeStepData1")</p>
<p>#Html.TextBox("RecipeStepData2")</p>
<p>#Html.TextBox("RecipeStepData3")</p>
</div>
<input type="submit" value="Submit" id="btn" />
}
Notice the order. I put the id first and then rest of the recipe step data so it gets bind properly.
For the begin form, You dont have to specify action and controller as you are doing the post on the same page. It doesnt hurt if you put there.
Hope this helps... :)
Why recipeID is null in in your posted data? It is your problem and
var recipe = db.Recipes.Single(r => r.recipeID == recipeID) cannot get recipeID=null because r.recipeID is not nullable.