I'm creating a Forum in asp.net MVC3 it contains link of Details which on click will show me details of particular record, but I am getting the following error when I click on the Details link.
The parameters dictionary contains a null entry for parameter 'id' of
non-nullable type 'System.Int32' for method
'System.Web.Mvc.ActionResult Details(Int32)' in
'Prjct_name.Controllers.DefaultController'. An optional parameter must
be a reference type, a nullable type, or be declared as an optional
parameter. Parameter name: parameters
Since I'm very new to MVC dont know how to deal with this
Still you want to use this URL [www.mydomain.com/Default/Details] you can set id as nullbale in controller :
public ActionResult Details(int? id)
{
if (id ==null)
{
// Do stuff
}
else
{ // Do something else
}
}
Sounds like your ActionResult looks like this:
public ActionResult Details(int id)
{
//Do stuff
}
Which would require the url be something like www.mydomain.com/Default/Details/1 where 1 is the id of the item but the url you are hitting is www.mydomain.com/Default/Details without the /[id]. In MVC, if one of your ActionResult prameters is 'id', that parameter is expected to be in the url...not the querystring.
Related
The following action does not require a querystring, but it does require the Id to be passed in the URL.
public ViewResult Details(int id)
{
Domain domain = db.Domains.Find(id);
return View(domain);
}
How do I change this so the name can be passed in the URL instead of the Id?
When I change that to the following, it produces an error "Sequence contains no elements" regardless of how I attempt to execute it.
public ViewResult Details(String name)
{
Domain domain = db.Domains.Where(d => d.Name == name).First();
return View(domain);
}
Any help is greatly appreciated.
"Sequence contains no elements" error is because your LINQ query is not returning any results for this where clause but you are trying to Apply the First() function on the result set (which is not available for your where condition in this case).
Use the First() function when you are sure that there is Atleast one element available in the resultset you are applying this function on. If there are no elements as the result of your LINQ expression, Applying First will throw the above error.
For the URL to have the name parameter instead of the integer id, just change the parameter type to string. Keep the variable name as id itself. because that is what the MVC Routing will use to help you write those pretty URLS.
So now your URL can be like
../SomeController/Details/someName
Where someName is going to be the parameter value of your Details action method.
I would use the FirstOrDefault and do a checking to see whether an element is available for the LINQ expression.FirstOrDefault will returns the first element of a sequence, or a default value if the sequence contains no elements.
public ViewResult Details(String id)
{
Domain domain = db.Domains.Where(d => d.Name == id).FirstOrDefault();
if(domain!=null)
return View(domain);
else
return View("NotFound") //Lets return the Not found View
}
In the index, I have the following link for the object to be edited:
<div class="editor-field">#Html.ActionLink("Edit", "Edit", new { id = thing.Id })</div>
At my controller, I have the following method signature:
public ActionResult Edit(Thing thing)
But This is not called, instead, an error is displayed which specifies null value is passed.
The link contains the required ID value of the object.
Do I need to change the signature of Edit method in the controller ?
Update:
The example fails even with the changes with the error message as
Server Error in '/' Application.
The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'MongoDB.Bson.ObjectId' for method 'System.Web.Mvc.ActionResult Edit(MongoDB.Bson.ObjectId)'
Do I need to change the signature of Edit method in the controller ?
Yes, since you are passing only an id parameter in your Html.ActionLink you can't expect to get something more in your Edit action:
public ActionResult Edit(string id)
{
Thing thing = ... go and fetch the thing from the id
...
}
I have and action which takes a userId parameter:
~/Users/Show?userId=1234
Everything works fine except when the userId provided is not an int or is missing.
Then it throws this exception:
Message: The parameters dictionary contains a null entry for parameter 'userId' of
non-nullable type 'System.Int32' for method 'System.Web.Mvc.ActionResult Show(Int32,
System.Nullable`1[System.Boolean], System.String)' in 'S4U.Web.Mvc.Controllers.ProfileController'. An optional parameter must be a reference type,
a nullable type, or be declared as an optional parameter.
Parameter name: parameters
..after which the user is redirected to the error page.
How do I configure the route so the action isn't hit at all and it throws a 404 instead?
Don't use a string as suggested somewhere below. Use:
public ActionResult (int userId = 0)
{
}
That's the best practise.
You can also do:
public ActionResult (int? userId)
{
if (userId.HasValue)
{
//...
}
}
As mentioned in my comment on Ufuk Hacıoğulları's answer you should handle validation either through adding a constraint to a route, through having a nullable type if the parameter can be empty.
For the former approach if you have an appropriate constraint this means your route will not be picked up - you will need a catch all route or other error handling. For the nullable type you can test in the action whether it has a value and act accordingly.
Keeping action paramters as strong types is a pattern to aim for.
I've created a routing structure whereas the action part of the URL serves as a dynamic handler for picking a specific user created system name. i.e.
http://mysite.com/Systems/[SystemName]/Configure, where [SystemName] designates the name of the system they would like to configure.
The method that routes the system is the following:
public ActionResult Index(string systemName, string systemAction)
{
ViewData["system"] = _repository.GetSystem(systemName);
if (systemAction != "")
{
return View(systemAction);
}
else
{
// No Id specified. Go to system selection.
return View("System");
}
}
The above method sets the system to configure and routes to a static method where the view is displayed and a form awaits values.
The question I have is that when I create my configuration view, I lose my posted values when the form is submitted because it routes back to the above Index controller. How can I determine if data is being posted when hitting my above Index controller so that I can make a decision?
Thanks!
George
Annotate the controller method that handles the POST like this:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(string systemName, string systemAction)
{
// Handle posted values.
}
You can have a different method in your controller that handles the GETs:
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Index(string systemName, string systemAction)
{
// No posted values here.
}
Note that, although I have copied the same method and parameters in each case, the signature for the second method (parameters and types) will have to be different, so that the two methods are not ambiguous.
The NerdDinner tutorial has examples of this.
I know that if I have an url like XController/Action?id=1, and an action method
void Action(int id)
the id parameter will automatically be read from the query string.
But how can I access the entire query string when I don't in advance know the name of all parameters. E.g:
void Action(QueryStringCollection coll) {
object id = coll["id"];
}
Is it possible to do something like this?
Use Request.QueryString for this
Request.QueryString.Keys gives you the name of all parameters