Postman. Issue with multipart/form-data (415 Unsupported Media Type) - asp.net-core

I got some issue during test my endpoint (with multipart/form-data) on Postman.
I have following method (some fields + photo). This method works with Swagger ok.
[HttpPost]
public async Task<bool> MailPhoto([FromForm] MailwithPhoto mailWithPhoto)
{...}
public class MailwithPhoto
{
public string mail_message { get; set; }
public IFormFile photo_file { get; set; }
public string userContact { get; set; }
public string category { get; set; }
public string userName { get; set; }
public string method { get; set; }
}
enter image description here

First need to change Key message to mail_message,or mail_message will not be binded.
415 is often due to Content-Type or Content-Encoding, or as a result of inspecting the data directly.
Here is a working demo(I use a .net core mvc project):
result:

Related

How to implement GET endpoint in ASP.NET Core which returns object with File?

I have the following class:
public class Person
{
public string Name { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public byte[] PersonPhoto{ get; set; }
}
Usually I implement get objects endpoint, which returns not directly file but path to that file, and second endpoint to retrieve file separately.
Is that any solution which will let me implement it from one endpoint?
Is it a good practice?

Posting mutipart/form-data with array of ints in .net core

I am trying to post a file to a .Net Core controller action with the following model (paired down from the actual class):
public class UploadDocumentModel
{
[Required]
public int[] Ids { get; set; }
[Required]
public string FileName { get; set; }
[Required]
public IFormFile File { get; set; }
}
Here is the action that receives the post:
public async Task<IActionResult> UploadDocument([FromForm]UploadDocumentModel documentModel)
The problem is that when I use Swagger or Postman to test it out while passing in an array of Ids, .Net Core throws a validation error:
"errors": {
"Ids": [
"The value '1,2' is not valid."
]
},
I could accept the Ids as just plain string (comma separated list of ids) and then parse them into an array of ints but I suspect I am missing something else here. Any help would be great!
Thanks!
Here is a demo to pass file and an array with Postman:
UploadDocumentModel:
public class UploadDocumentModel
{
[Required]
public int[] Ids { get; set; }
[Required]
public string FileName { get; set; }
[Required]
public IFormFile File { get; set; }
}
Controller:
public async Task<IActionResult> UploadDocument([FromForm]UploadDocumentModel documentModel) {
return Ok();
}
formdata:
result:

The new ASP.NET Core 3.0 Json serializer is leaving out data

I'm porting a web application to ASP.NET Core 3, and after a bit of a battle, I'm almost at the finish line. Everything seems to work, but all of a sudden my JSON data returned from the api is missing some levels.
It seems the options.JsonSerializerOptions.MaxDepth is default at 64 levels, so it can be that. Some other places where an option can be playing tricks on me?
This is the code (and a quickview of the value):
And this is the JSON I get in the browser:
So the ParticipantGroups property/collection is completely missing in the generated output.
Any ideas where this happens?
EDIT:
I've added a repo on Github that showcases the issue. Standard ASP.NET Core 3.0 solution, created from the template, with a change to the result returned from the Weatherforecast controller:
https://github.com/steentottrup/systemtextjsonissue
For now I've gone back to using Newtonsoft.Json, with the Microsoft.AspNetCore.Mvc.NewtonsoftJson package. Then when I have some time, I'll try finding out what the solution is, without Newtonsoft.Json.
The problem seems to be an error in the new version 3.0. At least it seems like an error to me.
It seems System.Text.Json will convert the class mentioned in the hierarchy, not the actual class. So if you are using an abstract class in the hierarchy, you're in trouble. The second I removed the base class, and used the actual class I'm returning, the problem goes away it seems.
So this doesn't work:
public class SurveyReportResult {
public Guid Id { get; set; }
public String Name { get; set; }
public Int32 MemberCount { get; set; }
public IEnumerable<OrganisationalUnit> OrganisationalUnits { get; set; }
}
public abstract class OrganisationalUnit {
public Guid Id { get; set; }
public String Name { get; set; }
public Int32 MemberCount { get; set; }
}
public class OrganisationalUnitWithParticipantGroups : OrganisationalUnit {
public IEnumerable<ParticipantGroup> ParticipantGroups { get; set; }
}
public class ParticipantGroup {
public Guid Id { get; set; }
public String Name { get; set; }
public Int32 MemberCount { get; set; }
}
This will only return the properties of the OrganisationalUnit class, not the additional property of the OrganisationalUnitWithParticipantGroups.
This works:
public class SurveyReportResult {
public Guid Id { get; set; }
public String Name { get; set; }
public Int32 MemberCount { get; set; }
public IEnumerable<OrganisationalUnitWithParticipantGroups> OrganisationalUnits { get; set; }
}
public class OrganisationalUnitWithParticipantGroups /*: OrganisationalUnit*/ {
public Guid Id { get; set; }
public String Name { get; set; }
public Int32 MemberCount { get; set; }
public IEnumerable<ParticipantGroup> ParticipantGroups { get; set; }
}
public class ParticipantGroup {
public Guid Id { get; set; }
public String Name { get; set; }
public Int32 MemberCount { get; set; }
}

Map GET request to Action

I'm trying to validate the progress quantity (and other fields once this works) that belongs to the BeginCollectionItems server side. The request is being sent but the parameter progressQty is not being read by the action.
This is the action I'm trying to map to:
[AllowAnonymous]
[AcceptVerbs("Get", "Post")]
public IActionResult CheckValidProgressQty(int progressQty)
{
int a =progressQty;
var result = false;
if (a > 0)
result = true;
return Json(result);
}
This is the request:
:method: GET
:path: /Components/CheckValidProgressQty?ProgressItems%5B16bad1f2-155c-4a29-844c-34e88da80b7c%5D.ProgressQty=-300
This is the Query String Parameters:
ProgressItems[16bad1f2-155c-4a29-844c-34e88da80b7c].ProgressQty: -300
Here is the remote validation in the View Model Class:
[Remote(action: "CheckValidProgressQty", controller: "Components", HttpMethod ="GET", ErrorMessage = "BAD QTY!")]
public int ProgressQty { get; set; }
Right now it goes into the CheckValidProgressQty method but I'm just not able to access the progressQty parameter. One way I can access is:
Request.QueryString.Value
?ProgressItems%5B16bad1f2-155c-4a29-844c-34e88da80b7c%5D.ProgressQty=-8
and parse it. But I think there should be something more simple available.
ProgressItems[16bad1f2-155c-4a29-844c-34e88da80b7c].ProgressQty: -300
This is posted form data when you do POST method not for GET method.
You could not get the query string on your action parameters using ?ProgressItems%5B16bad1f2-155c-4a29-844c-34e88da80b7c%5D.ProgressQty=-300since they are not match.
Refer to my below demo which introduces how to pass querystring to action, assume that I have models:
public class TestUser
{
[Key]
public int Id { set; get; }
public string Name { get; set; }
public IList<UserInterest> Interests
{
get; set;
}
}
public class UserInterest
{
[Key]
public int Id { set; get; }
[Required]
public string InterestText { set; get; }
public int Option { set; get; }
}
You need to use an object like
public ActionResult UserTest(TestUser model)
And the querystring is ?Interests[0].InterestText=hello

MVC4 Mailgun delivered webhook

I'm having an issue making use of the Mailgun delivered webhook, it can be found here: http://documentation.mailgun.net/user_manual.html#events-webhooks, look for "Delivered Event Webhook"
I am unable to reference Request.Params["Message-Id"] unless I modify the app's requestValidationMode to 2.0
I do get the potentially unsafe error when trying to reference this field without requestValidationMode = 2.0. The contents of the field are: <20130203200110.12345.12345#mydomain.mailgun.org>. I've also tried to declare a model to take advantage of auto model binding. My model looks like this:
public class MailgunDeliveredEvent
{
public string Id { get; set; }
public string Event { get; set; }
public string Recipient { get; set; }
public string Domain { get; set; }
[AllowHtml]
[JsonProperty(PropertyName="Message-Id")]
public object MessageId { get; set; }
public int Timestamp { get; set; }
public string Token { get; set; }
public string Signature { get; set; }
}
When I attempt to reference the MessageId field it returns null. I've tried to add
[Bind(Exclude="message-headers")]
As I'm not interested in that field.
In the Controller, I've set
[ValidateInput(false)]
I can't seem to get the Message-Id field back. Any help?
I seem to have got it working, in case anyone runs into the same issue...
I added a new model binder as referenced here:
Asp.Net MVC 2 - Bind a model's property to a different named value
I then changed my model like so:
[ModelBinder(typeof(DefaultModelBinderEx))]
public class MailgunDeliveredEvent
{
public string Id { get; set; }
public string Event { get; set; }
public string Recipient { get; set; }
public string Domain { get; set; }
[BindAlias("Message-Id")]
public string MessageId { get; set; }
public int Timestamp { get; set; }
public string Token { get; set; }
public string Signature { get; set; }
}
And all seems to work, I didn't need to call
[ValidateInput(false)]
on the controller either.
Hope that helps someone.