'The parameters dictionary contains a null entry' error, Web API - c#

On my Web API I have a Document Controller with two simple actions:
[AllowAnonymous]
public class DocumentController : ApiController
{
public String Get(int id)
{
return "test";
}
public String Get(string name)
{
return "test2";
}
}
The following URL (executes the first function) works fine:
http://localhost:1895/API/Document/5
But this URL (should execute the second function):
http://localhost:1895/API/Document/test
Throws this error:
{
"message": "The request is invalid.",
"messageDetail": "The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Int32' for method 'xx.yy.Document Get(Int32)' in 'API.Controllers.DocumentController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter."
}
This is the MapHttpRoute in the WebApiConfig:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
What am I doing wrong? Please advise.

Your second function has a parameter name, and the default parameter is called id. With your current setup, you can access the second function on
http://localhost:1895/API/Document/?name=test
To make the URLs work as you have specified previously, I would suggest using attribute routing and route constraints.
Enable attribute routing:
config.MapHttpAttributeRoutes();
Define routes on your methods:
[RoutePrefix("api/Document")]
public class DocumentController : ApiController
{
[Route("{id:int}")]
[HttpGet]
public String GetById(int id) // The name of this function can be anything now
{
return "test";
}
[Route("{name}"]
[HttpGet]
public String GetByName(string name)
{
return "test2";
}
}
In this example, GetById has a constraint on the route ({id:int}) which specifies that the parameter must be an integer. GetByName has no such constraint so should match when the parameter is NOT an integer.

Related

How to dynamically specify Query String in Web API URL

I am new to c# and web api. I have a WebAPI controller with a Get method as follows:
public class peopleController : ApiController
{
[HttpGet]
public IHttpActionResult getAllPeople(string Name, string Age)
{
//Return something
}
}
My WebApiConfig is like this:
config.Routes.MapHttpRoute(
name: "getAllPeopleApi",
routeTemplate: "people",
defaults: new { controller = "people", action = "getAllPeople" }
);
If I invoke my url like this : http://localhost:xxx/people?Name=&Age=. It working fine.
But when I invoke like all these:
http://localhost:xxx/people,http://localhost:xxx/people?Name=,http://localhost:xxx/people?Age=
I got this error message:
{"Message":"No HTTP resource was found that matches the request URI 'http://localhost:xxxx/......'.","MessageDetail":"No action was found on the controller 'people' that matches the request."}
I try to set my routeTemplate: "people/{Name}/{Age}". Now when I run this web api Error 404.0 Not Found
routeTemplate: "people/{Name}/{Age}"
This part is not a QueryString, this is a dynamic path.
That means that your path becomes Domain/people/SomeName/SomeAge?QueryString=Whatever
Managed to solve this by explicitly set parameter Name and Age to Null.
public class peopleController : ApiController
{
[HttpGet]
public IHttpActionResult getAllPeople(string Name = null, string Age=null)
{
//Return something
}
}
This will made the parameters as an optional parameters. Now you can invoke the controller with or without Query string parameter.

Error When trying to Register a User in asp.net mvc

Hi I have Faced With a Problem When Im Trying To Register.
This Is My Code :
public ActionResult RegisterButton(Models.Users User)
{
using (MyDbContext db = new MyDbContext())
{
if (ModelState.IsValid == false)
{
return View("Register", User);
}
else
{
db.Users.Add(User);
db.SaveChanges();
Session["UserId"] = User.Id;
//Directory.CreateDirectory(string.Format("~/App_Data/{0}",User.UserName+User.Id.ToString()));
return RedirectToAction("Profile", "Profile",new { User.Id});
}
}
}
And This Is Also My Route Config Code :
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
And I Get This Error :
The parameters dictionary contains a null entry for parameter 'UserId' of non-nullable type 'System.Int32' for method 'System.Web.Mvc.ActionResult Profile(Int32)' in 'DigiDaroo.Controllers.ProfileController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter.
Please Help:|
Based on the code you provided, your RegisterButton method will return a redirect response to the browser with location header value like this
/Profile/Profile/101
Where 101 is replaced with the actual ID of the new User record. With the routing configuration you have, your code would not throw that error message if your action method parameter name is id. Since you are getting the error message, i assume your action method parameter name is something else. So make sure you are explicitly passing that the routeValue object.
For example, if your action method parameter name is userId like this
public ActionResult Profile(int userId)
{
// to do : return something
}
your redirect response call should be like this
return RedirectToAction("Profile", "Profile",new { userId = User.Id});
This will send the location header value for the redirect response as /Profile/Profile?userId=101 and browser will use this to make the GET request. since we are explicitly passing the userId parameter in querystring, your error parameter will be properly filled with the value 101
Another option is to change your action method parameter name to id
public ActionResult Profile(int id)
{
// to do : return something
}

WebApiConfig & what is the difference between routes

I have a WebApiController that implements two Get method: one that does not require a parameter and the other method requires an interger parameter...
//Get api/<controller>
public IEnumerable<EmployeeVM> Get()
{
List<EmployeeVM> list = new List<EmployeeVM>()
{
new EmployeeVM(){
FullName = "Milton Waddams"
},
new EmployeeVM(){
FullName = "Andy Bernard"
}
};
return list;
}
//Get api/<controller>
public string Get(int id)
{
return "value";
}
If I use the following configuration in my WebApiConfig class,
configuration.Routes.MapHttpRoute("API Default", "api/{controller}/{id}", new { id = RouteParameter.Optional });
then I would get the following error:
"The parameters dictionary contains a null entry for parameter 'id' of
non-nullable type 'System.Int32' for method 'System.String Get(Int32)'
in 'AngularForMVC.Controllers.EmployeeWebApiController'. An optional
parameter must be a reference type, a nullable type, or be declared as
an optional parameter."
Now if I use the this following configuration:
configuration.Routes.MapHttpRoute("API Default", "api/{controller}/{action}/{id}", new { id = RouteParameter.Optional });
then it works. I can execute the Get() method without any errors.
What is the difference? Why does the second code reference work? I know that I added an {action} into the url path, but even if I did not include the {action} path to the url this should still work.
You should give the id parameter as a nullable int. Get(int? id)
I always prefer using [Route] attribute to define my routes configurations than add new roles in route.config
https://www.asp.net/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2
A custom [Route] would be better for several reasons
1-Is to identify what each GET request is supposed to do.
for example if you have [Route("api/getlist")] and [Route("api/getitem/{id}")]
this would be more descriptive.
2-You won't face the problem you're facing now.

Why am I getting an error when calling a webservice function?

I am coding a C# web api 2 webservice and would like some help to get a single item from a request to a webservice.
Here is the web service controller class code:
[RoutePrefix("api")]
public class ItemsWebApiController : ApiController
Here is the web service function:
// GET: api/Getitem/1
[Route("Getitem")]
[System.Web.Http.HttpGet]
[ResponseType(typeof(Item))]
public async Task<IHttpActionResult> GetItem(int id)
{
Item item = await db.items.FindAsync(id);
if (item == null)
{
return NotFound();
}
return Ok(item);
}
Here is the uri to the IIS website:
http://localhost/thephase
Here is the uri that I am accessing:
http://localhost/thephase/api/Getitem/1
Here is the error that is being displayed in the browser:
{"Message":"No HTTP resource was found that matches the request URI
'http://localhost/thephase/api/GetItem/1'.","MessageDetail":"No type
was found that matches the controller named 'GetItem'."}
Here is the WebApiConfig code:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
var appXmlType = config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml");
config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);
}
}
The error states that the controller is named 'GetItem', and this is incorrect. Hence I am thinking that the problem is in the WebApiConfig route code.
If I remove the int id from the function, then the function is called correctly.
Here is the same function with no parameter:
// GET: api/Getitemnoparameter
[Route("Getitemnoparameter")]
[System.Web.Http.HttpGet]
[ResponseType(typeof(Item))]
public async Task<IHttpActionResult> GetItem()
{
Item item = await db.items.FindAsync(1);
if (item == null)
{
return NotFound();
}
return Ok(item);
}
The following uri accesses the function correctly:
http://localhost/thephase/api/Getitemnoparameter
So the problem has something to do with the int parameter.
Can someone please help me to get access the GetItem function with a parameter?
Because you are using Attribute Routing you also need to specify the parameter for it to work.
Check this tutorial out for a better understanding.
Route Prefixes
[Route("Getitem/{id:int}")]
The Id is an int. int is a value type. Value types cannot be null. You set the parameter to RouteParameter.Optional, but if it's optional, it must be able to be assigned null.
Solution: Use a nullable int
public async Task<IHttpActionResult> GetItem(int? id)

ASP.net WebApi newly registered route says, that request is invalid

I'm setting up backend for my Windows Phone 8.1 App. I'm using ASP.net WebApi to create RESTful api for accessing data from DB, which is set up on Windows Azure.
This is how my routes looks:
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "DefaultNamedApi",
routeTemplate: "api/{controller}/{name}",
defaults: new { name = RouteParameter.Optional }
);
What i'm trying to achieve is accesing data using not an integer - I want to access data using a string.
This is code from my WebApi controller:
private SmokopediaContext db = new SmokopediaContext();
// GET api/Images
public IQueryable<ImageModel> GetImageModels()
{
return db.ImageModels;
}
// GET api/Images/5
[ResponseType(typeof(ImageModel))]
public IHttpActionResult GetImageModel(int id)
{
ImageModel imagemodel = db.ImageModels.Find(id);
if (imagemodel == null)
{
return NotFound();
}
return Ok(imagemodel);
}
public IHttpActionResult GetImageModel(string name)
{
ImageModel imagemodel = db.ImageModels.Find(name);
if(imagemodel == null)
{
return NotFound();
}
return Ok(imagemodel);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
private bool ImageModelExists(int id)
{
return db.ImageModels.Count(e => e.ID == id) > 0;
}
Most important code is an overload to GetImageModel with string parameter.
Server is returning error which says that parameter of url is incorrect:
<Error><Message>The request is invalid.</Message><MessageDetail>The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Int32' for method 'System.Web.Http.IHttpActionResult GetImageModel(Int32)' in 'Smokopedia.Controllers.DragonController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter.</MessageDetail></Error>
What should I correct in my route?
There is no difference in URI template terms between api/{controller}/{id} and api/{controller}/{name}; the arbitrary names you assign to the parameters can't be used in resolving the route.
Take a look at Overload web api action method based on parameter type for an example of how to "overload" routes based on parameter types.
Use Attribute Routing:
[Route("api/Images/{id:int}")]
public IHttpActionResult GetImageModel(int id){ do something}
[Route("api/Images/{id}")]
public IHttpActionResult GetImageModel(string id) {do something}
Your url/query is important here.
You are probably using:
http://yourapp.address/<Controller>/<name>
That will not work in this registration. Your routing matches that address to first matching route. Ant that is DefaultApi. You must use
http://yourapp.address/<Controller>?name=<name>
or change Your routing.

Categories