Test Mailgun incoming emails locally - c#

I'm implementing feature of getting Incoming Emails from Mailgun. I created action:
[Route("incoming-email/notify")]
[HttpPost]
public async Task<IActionResult> NotifyIncomingEmail([FromForm] CreateIncomingEmailCmd cmd)
{ ... }
and want to debug it locally (send to localhost) to check if params are mapped correctly.
So, for example if I send via Postman as x-www-form-urlencoded param body-html then it isn't mapped to my property BodyHtml of CreateIncomingEmailCmd class and [JsonProperty("body-html")] didn't help.
How can I do that?

You could try to use ModelBinder attribute to specify the name of the property like below:
public class CreateIncomingEmailCmd
{
[ModelBinder(Name = "body-plain")]
public string BodyPlain { get; set; }
[ModelBinder(Name = "body-html")]
public string BodyHtml { get; set; }
}

Related

POST request: How do I have 1 [FromBody] class/object argument + 1 IFormFile argument in the same request?

I am looking to receive 1 CNCTask class object from the body, but I also need to transfer a file in the same POST request. I have written out my POST route definition as:
[HttpPost("TaskUpload")]
[Consumes("application/json")]
public async Task<ActionResult<CNCTask>> Post([FromBody] CNCTask task, IFormFile file)
With my route defined as such, I just don't get how I will even transfer the file (e.g. when testing from Postman). A file would usually be sent in the body (I think ?), but if I already have my CNCTask object being selected by the [FromBody], how do I negotiate this file transfer as well ?
I'm quite confused as to how to send both the class object and the file. Any tips would be appreciated.
EDIT
text body request that only includes a CNCTask object
{
"description":"truc",
"completion":24,
"machine":{
"hostname":"some host",
"port": 1234
}
}
form-data body request that includes the full Payload (CNCTask + IFormFile)
This was tested using a Postman and Visual studio.
You have to create a model class
public class CNCTask
{
public string Description { get; set; }
public int Completion { get; set; }
public Machine Machine { get; set; }
public IFormFile File { get; set; }
}
public class Machine
{
public string Hostname { get; set; }
public int Port { get; set; }
}
action
[HttpPost("TaskUpload")]
public async Task<ActionResult<CNCTask>> Post(CNCTask model)
and you can test it using postman
You can retrive form data as follows
var formdata = Request.Form["formdata"];
var model = JsonConvert.DeserializeObject<ModelEntity>(formdata);
And write your controller this way
public async Task<ActionResult<CNCTask>> Post(IFormFile file)
{
var formdata = Request.Form["formdata"];
var model = JsonConvert.DeserializeObject<InitialDemandEntity>(formdata);
...
}

POST Image and Body Data at the same time in ASP.NET Core WEB API

I am trying to POST image file and a set of parameters using ASP.NET Core. Is there any option/solution to send both Model Data and Image at the same time in POST API. Here is the image of POST API in POSTMAN:
Here is body with Model Information:
If I do it like following code then my companyInfo data is null and image is there.
[HttpPost("PostInformation")]
public async Task<ActionResult<Company>> PostEmployeeJobCategories(IFormFile image, [FromForm]Company companyInfo)
{
}
If I do it like following code then I am getting Unsupported Media Type.
[HttpPost("PostInformation")]
public async Task<ActionResult<Company>> PostEmployeeJobCategories([FromForm]IFormFile image, [FromBody]Company companyInfo)
{
}
Any Advise, how to achieve the goal ?
Thank You
Adding [FromForm] attribute and sending everything through form-data tab in Postman works for me:
public class OtherData
{
public string FirstString { get; set; }
public string SecondString { get; set; }
}
public async Task<IActionResult> Post(IFormFile file, [FromForm]OtherData otherData)
{
return Ok();
}
As vahid tajari pointed out, you can also add your IFormFile to the class definition.
In asp.net core, you can send file and data together, so change your model to:
public class Company
{
public IFormFile Image { get; set; }
public string NameEn { get; set; }
public string Address { get; set; }
//......
}
And your action method to:
[HttpPost("PostInformation")]
public async Task<ActionResult<Company>>PostEmployeeJobCategories([FromForm] Company companyInfo)
{
}

Multiple Bind(Prefix = "...") in ASP.Net Core 3 MVC

I've an ASP.Net MVC 4 application that I'm porting to ASP.Net Core 3.0 MVC.
I'm trying to port this method
[HttpPost]
public ActionResult DoSave(
[Bind(Prefix = "new")]IEnumerable<C_Data> newItems,
[Bind(Prefix = "updated")]IEnumerable<C_Data> updatedItems,
[Bind(Prefix = "deleted")]IEnumerable<C_Data> deletedItems))
{
}
In the post AJAX (in JavaScript from the web browser) I'm sending the values as JSON like this
{
"new[0].Id":3,
"new[0].SID":"00000000-0000-0000-0000-000000000000",
"new[0].Name":"asd"
}
Here's the C_Data class
public class C_Data
{
[Key]
public int Id { get; set; }
public Guid SID { get; set; }
[Required]
[MaxLength(40)]
public string Name { get; set; }
}
But the three parameters are empty when this action is executed.
Here's the error I get in the ModelState
"The JSON value could not be converted to C_Data"
Anyone please can tell me how to port this method?
Thank you.
PD: This action is in an MVC controller not an API controller.
Here's a link that should help.
It looks like you should be able to use C_Data object, put it in an array, and stringify it in the AJAX call, receive an IEnumerable.
For Asp.Net Core, there are two ways to bind the model, ModelBinding and JsonInputFormatter. For sending request with json, it will use JsonInputFormatter and Bind will not work.
In general, I would suggest you try option below:
Controller Action
[HttpPost]
public ActionResult DoSave([FromBody]ItemModel itemModel)
{
return Ok("Worked");
}
Model
public class ItemModel
{
public IEnumerable<C_Data> NewItems { get; set; }
public IEnumerable<C_Data> UpdatedItems { get; set; }
public IEnumerable<C_Data> DeletedItems { get; set; }
}
Request Json
{
"newItems":[{
"Id":3,
"SID":"00000000-0000-0000-0000-000000000000",
"Name":"asd"
}]
}

Pass angular querystring to API controller as C# class by http.get

I am sending request. And i want map parameters to C# class in Asp.Net Core Web.API controller. When i write to my method property name as parameter, it is working. But, i write class then it gave me error like "The input was not valid."
I am sending my request by Postman as "Get"request. My request is
http://localhost:5002/api/user/GetUsers?PageFirstIndex=0&IsSortAscending=true&PageSize=10&SortBy=Id
When i wrote like this, it is working and all parameters came with value.
public async Task<ServiceResult> GetUsers(string SortBy, bool IsSortAscending, int Page, byte PageSize)
{...}
But when i wrote like this as class, gave me error "The input was not valid.".
[HttpGet("GetUsers")]
public async Task<ServiceResult> GetUsers(QueryObject queryFilter)
{...}
public class QueryObject
{
public string SortBy { get; set; }
public bool IsSortAscending { get; set; }
public int PageFirstIndex { get; set; }
public byte PageSize { get; set; }
}
You need to use the FromQuery attribute.
public async Task<ServiceResult> GetUsers([FromQuery]QueryObject queryFilter) {}
See the model binding documentation.

Using [FromUri] and [FromBody] simultaneously to bind a complex Web Api method parameter

I am using request and response models to encapsulate data that needs to be passed to methods in my ASP.NET Web Api, using [FromUri] and [FromBody] when necessary.
There are instances, however, in which I would like to use both Uri and Body to populate the properties of my request model. An example would be in updating a user, where the UserId should be passed in the Uri, but the data to update would be passed in the body content. My desired implementation would look something like this:
Model:
public class UpdateUserRequestModel
{
public string UserId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string DisplayName { get; set; }
}
Api Method:
[HttpPut]
[Route("Update/{UserId}")]
// PUT: api/Users/Update/user#domain.net
public async Task UpdateUserAsync(UpdateUserRequestModel model)
{
// Method logic
}
I would like the property UserId to be obtained [FromUri], but the rest to be obtained [FromBody], all while keeping everything all parameters in a single object. Is this possible?
Not the cleanest solution but it should work:
[HttpPut]
[Route("Update/{UserId}")]
// PUT: api/Users/Update/user#domain.net
public async Task UpdateUserAsync(UpdateUserRequestModel model, int UserId)
{
model.UserId = UserId;
}

Categories