POST parameter is null in when it's a hand made type - entity-framework

I have a asp.net 4.5.2 web api and one POST method receive a DTO parameter I've coded by hand like these:
using System;
namespace WebApi.Models.DTO
{
[Serializable]
public class MyModelDto
{
public MyModelDto()
{
}
public int Id { get; set; }
public string Code { get; set; }
public int Type { get; set; }
}
}
When I call this method from Postman the parameter is always null, but if I design the same DTO class in EntityFramewok (edmx model) and use it as parameter I could receive the data inside the post method as it was send.
I could not realize what I'm missing in my hand made class?
Why it works using EF and not with my class?
Setting the parameter as dynamic also works...
[HttpPost]
[JwtAuthentication]
[Route("api/bills/invoice")]
public JsonResult<WebApi.Models.DTO.MyModelDto> Post(WebApi.Models.DTO.MyModelDto param)
{
// Here param is always NULL
}
[HttpPost]
[JwtAuthentication]
[Route("api/bills/invoice")]
public JsonResult<Data.MyModelDto> Post(Data.MyModelDto param)
{
// Here param wors! based on the EF class
}
public JsonResult<Data.MyModelDto> Post(dynamic param)
{
// Here param wors! using dynamic data type
}

it depends how you send the data via Postman.
I don't have Postman here to test but make sure you select Json Type when sending data and then your sent data needs to match your DTO. Something like:
{
"Id":1,
"Type":"whatever",
"Code":"whatever"
}
This data goes in the body of the request since you are sending a Post request.
One extra observation, your DTO does not need an empty constructor, you can get rid of it. There is nothing wrong with:
public class MyModelDto
{
public int Id { get; set; }
public string Code { get; set; }
public int Type { get; set; }
}
For testing purposes get rid of your Jwt authentication, until you get the calls running correctly

Related

Web API controller parameter is null only on GET request

So I have a very simple controller that accepts a Search object
public class ProfileController : ApiController
{
[AcceptVerbs("GET", "POST")]
public async Task<ProfileDTO> GetProfile(Search profile)
{
//My code
}
}
The Search object only contains very simple, primitive data types
public class Search
{
public string Uuid { get; set; }
public string Email { get; set; }
public string Name { get; set; }
public bool Censored { get; set; }
}
For testing purposes I am using Swagger to call my API with sample data. For some reason if I make the same call to api/profile with the same data the profile argument will only contain data during the POST call. On a GET it is always null.
I only added the AcceptVerbs("POST") to demonstrate this issue, but by RESTful design I want the endpoint to only accept GET verbs
As of right now I'm just sending some boilerplate sample data such as
{
"Uuid": "string",
"Email": "string",
"Name": "string",
"Censored": true
}
I know this is probably a very simple issue, but why is the parameter always null only on a GET request?

How to pass query string parameter to asp.net web api 2

How can I pass more than 1 parameters as part of query string to my asp.net web api 2.
This is my asp.net web api 2 method, I am not able to figure out that how can I decorate this method so that it accepts the id and a complex type which is CustomerRequest, I want to use Url something like
http://localhost/api/Customer/?Mobile0012565987&Email=abcxyz.com&IsEmailVerified=true
[ResponseType(typeof(Customer))]
public IHttpActionResult GetCustomer(long id, [FromUri]CustomerRequest request)
{
var customer = db.Customers.Find(request.CustomerId);
if (customer == null)
{
return NotFound();
}
return Ok(customer);
}
This is CustomerRequest class
public class CustomerRequest
{
public string Mobile { get; set; }
public string Email { get; set; }
public Nullable<bool> IsEmailVerified { get; set; }
}
Otherwise pleaase guide me if there is a better way to do it.
Thanks
Based on your code, you need to pass 'id' as well, like this:
http://localhost/api/Customer/?id=12345&Mobile=0012565987&Email=abcxyz.com&IsEmailVerified=true
if you want to make 'id' optional, you can make your method signature look like this:
public IHttpActionResult GetCustomer([FromUri]CustomerRequest request, long id = 0)
this will set id to 0 by default, if you dont pass it in the URL. So you will be able to access your URL like you originally did:
http://localhost/api/Customer/?Mobile=0012565987&Email=abcxyz.com&IsEmailVerified=true

How to ignore properties marked with [IgnoreDataMember] when calling REST service

I am consuming a REST Xml service.
I have all the necessary classes to do this, (supplied by the dev who wrote the service) but at my end I have to save some of the responses to the DB to perform the tasks of the app I am writing.
So I have marked some of these classes I need to put in the DB as partial and extended them so that I can inherit from a DbEntity class which specifies an ID property so I can use EF to save them to the DB thus:
public interface IDbEntity
{
int ID { get; set; }
}
[Serializable]
public class DbEntity : IDbEntity
{
[IgnoreDataMember]
[XmlIgnore]
public int ID { get; set; }
}
the problem I am facing now, is that when the service call is being de-serialized I get the error
Error in line 1 position 113. 'Element' 'ElementName' from namespace '' is not expected. Expecting element '_x003C_ID_x003E_k__BackingField'
I am simply making the call like this:
var response = await client.PostAsXmlAsync<TReq>("Some/API/Call", req);
TResp val = await msg.Content.ReadAsAsync<TResp>(response)
all the properties in the original classes have Orders specified with their DataMember attributes and I have clearly marked my DB properties to be Ignored, but to no avail.
is there any way I can get this to work? - ie getting the DataContractSerializer to actually ignore the properties I have marked to be ignored when de-serializing?
as an aside, these ignored properties are also being passed to the service when making a call - does IgnoreDataMember actually do anything?
seems that the way to do this is like this
public interface IDbEntity
{
int ID { get; set; }
}
[Serializable]
[DataContract]
public class DbEntity : IDbEntity
{
[XmlIgnore]
public int ID { get; set; }
}
so basically adding the DataContract Attribute but omitting the DataMember attribute on the item you don't want
don't know how I missed that first time around. seems its opt in rather than opt out in this instance.

Using Generic Type DTO In ServiceStack Request

I was wondering if it's possible to use a Templated DTO requested of the type public class
RequestDTO<T, U> where T : class where U : class
{
public T ContextRequest { get; set; }
public U Request { get; set; }
}
And pass it to my service's request...
I've tried a simple example of type
public class MyContext
{
//removed some fields
public int IdUser {get;set;}
}
public class MyType1Request
{
public int IdRequest {get;set;}
}
public class MyType2Request
{
public DateTime SomeReallyImportantDate { get; set; }
}
public class UtenteService : Service
{
public UtenteService()
{
}
public string Any(RequestDTO<MyContext,MyType1Request> request)
{
return string.Format("User:{0} - IDRequest: {1}", request.ContextRequest.IdUser, request.Request.IDRequest);
}
public object Any(RequestDTO<MyContext, MyType2Request> request)
{
return string.Format("Utente:{0} - Data : {1}", request.ContextRequest.IDUtente, request.Request.DataLavorativa);
}
But I got this as far I try to access to the service
Sequence contains more than one matching element
Another solution is to implement in each my DTO Request object a IContext (and maybe IContextExt IContextSpecificManner) into the request object...but I would prefer to use the first approach
Thanks
AFAIK - This should work. The only thing that I am missing here is, you need to register route in apphost like:
Routes.Add>("/Utente/{IdUser}/{IdRequest}")

WebApi OData: $filter 'any' or 'all' query not working

First, using the ASP.NET WebApi tutorials I've created a basic ApiController that exposes an Entity Framework model through OData. The service works to return json for OData $filter queries.
When I perform OData $filter queries that include "any" or "all" queryies on a multi-value property it throws an ODataException
Here's the OData query I'm trying to use
~/api/Blogs?$filter=any(Tags,Name+eq+'csharp')
My ApiController looks like this:
public class BlogController : ApiController
{
public BlogsController()
{
this.Entities = new BlogEntities();
}
public ContactEntities Entities { get; set; }
[Queryable(PageSize = 25, AllowedQueryOptions = AllowedQueryOptions.All)]
public IQueryable<Blog> Get()
{
return this.Entities.Blogs;
}
}
The Blog entity has this contract
public Blog {
public Guid ID { get; set; }
public string Title { get; set; }
public Tag Tags { get; set; }
}
public Tag {
public Guid ID { get; set; }
public string Name { get; set; }
}
The exception thrown
ODataException: Type 'Blog' does not have a property 'Name'
As you can see, I have nothing out of the ordinary in my code and everything should work fine. Is it possible that "any" and "all" queryies aren't supported yet in Microsoft ASP.NET Web API OData?
Your any needs to be changed a bit. Try something like this:
~/api/Blogs?$filter=Tags/any(tag: tag/Name eq 'csharp')
This is assuming Tags actually returns a collection of Tags, not just a single Tag like you have above.
$inlinecount is only supported out of the box for the OData format. I wrote extensively about it here:
Web API OData Inlinecount not working
The short answer is that you can get it working for other formats with code that looks like this:
public PageResult<Customer> Get(ODataQueryOptions<Customer> queryOptions)
{
IQueryable results = queryOptions.ApplyTo(_customers.AsQueryable());
return new PageResult<Customer>(results as IEnumerable<Customer>, Request.GetNextPageLink(), Request.GetInlineCount());
}