I have an ASP.NET MVC Controller defined like so:
[HttpPost]
public string uploadQAImage(FileUploadClass fileUploadClass, HttpPostedFile image)
{
}
And this what the class FileUploadClass looks like.
public class FileUploadClass
{
public string job { get; set; }
public string createdBy { get; set; }
public string itemId { get; set; }
}
What I am trying to do with Alamofire in iOS is call this Controller, I have tried using parameters:
func saveQAPhotos(_ cellHolder: PhotoClass, completion: #escaping (_ result: Dictionary<String, Any>) -> Void)
{
let parameters: Parameters = [
"job" : cellHolder.job!,
"itemId" : cellHolder.itemId!,
"createdBy" : appDelegate.username!
]
let urlComponents = NSURLComponents(string: webservice + "uploadQAImage");
urlComponents?.user = appDelegate.username;
urlComponents?.password = appDelegate.password;
let url = urlComponents?.url;
Alamofire.upload(multipartFormData: { (multipartFormData) in
for (key, value) in parameters {
multipartFormData.append("\(value)".data(using: String.Encoding.utf8)!, withName: key as String)
}
if let data = cellHolder.photo {
multipartFormData.append(data, withName: "image", fileName: "image.png", mimeType: "image/png")
}
}, usingThreshold: UInt64.init(), to: url!, method: .post, headers: nil) { (result) in
switch result{
case .success(let upload, _, _):
upload.responseJSON { response in
if let result = response.result.value {
let jsonData = result as! Dictionary<String, Any>
completion(jsonData)
}
}
case .failure(_):
print("error")
}
}
}
But that didn't work on the ASP.NET side I get this error:
can't bind multiple parameters to the request's content
I have also tried sending the data as [AnyHashable: Any] like so:
func saveQAPhotos(_ cellHolder: PhotoClass, completion: #escaping (_ result: Dictionary<String, Any>) -> Void)
{
var jsonDict = [AnyHashable: Any]()
jsonDict["job"] = cellHolder.job
jsonDict["itemId"] = cellHolder.itemId
jsonDict["createdBy"] = appDelegate.username
let jsonData: Data? = try? JSONSerialization.data(withJSONObject: jsonDict, options: .prettyPrinted)
let urlComponents = NSURLComponents(string: webservice + "uploadQAImage");
urlComponents?.user = appDelegate.username;
urlComponents?.password = appDelegate.password;
let url = urlComponents?.url;
Alamofire.upload(multipartFormData: { (multipartFormData) in
multipartFormData.append(jsonData!, withName: "fileUploadClass", mimeType: "application/json")
if let data = cellHolder.photo {
multipartFormData.append(data, withName: "image", fileName: "image.png", mimeType: "image/png")
}
}, usingThreshold: UInt64.init(), to: url!, method: .post, headers: nil) { (result) in
switch result{
case .success(let upload, _, _):
upload.responseJSON { response in
if let result = response.result.value {
let jsonData = result as! Dictionary<String, Any>
completion(jsonData)
}
}
case .failure(_):
print("error")
}
}
}
Same error as before
can't bind multiple parameters to the request's content
Now when I change the ASP.NET Controller to only get FileUploadClass like so:
[HttpPost]
public string uploadQAImage(FileUploadClass fileUploadClass)
{
}
I get this error:
Object reference not set to an instance of an object.
I can only assume if I do fix the can't bind multiple parameters to the request's content error I will get this error next.
I am pretty sure I am sending the data incorrectly, so I guess my question is how do I send data from Alamofire upload method to an ASP.NET MVC method?
Related
My Angular (front-end) is making a POST request with JSON body and sends it to the server as follows :
const reponse = {
"Id_Harry" : this.harry.getId,
"x_harry" : this.harry.getX(),
"y_harry" : this.harry.getY(),
"Pv_Harry" : this.harry.getPv(),
"Force_Harry" : this.harry.getForce()
};
fetch(url, {
method: 'POST',
body: JSON.stringify(reponse),
headers :{
"Content-Type" : "application/json ,charset=UTF-8"
}
}).then((resp) => resp.json()).then(function(response) {
console.info('fetch()', response);
return response;
});
The back-end doesn't seem to recognize the server json body.The back-end code is a post that updates all the database with the values given by the json body.
The backend code is :
[Route("api/Harry/update")]
[HttpPost]
public IHttpActionResult PostHarry([FromBody] HarryViewModel harry)
{
try
{
if (harry == null)
{
return NotFound();
}
HarryDTO ha = new HarryDTO();
ha.Id_Harry = harry.Id_Harry;
ha.Pv_Harry = harry.Pv_Harry;
ha.Force_Harry = harry.Force_Harry;
ha.x_harry = harry.x_harry;
ha.y_harry = harry.y_harry;
_harryService.UpdateHarry(ha);
return Content(HttpStatusCode.OK,"OK");
}
catch (Exception ex)
{
return Content(HttpStatusCode.InternalServerError, "Something happenes!");
}
}
HarryViewModel class is :
public class HarryViewModel
{
public int Id_Harry { get; set; }
public int Pv_Harry { get; set; }
public int Force_Harry { get; set; }
public int x_harry { get; set; }
public int y_harry { get; set; }
}
The back-end doesn't seem to recognize the Angular json format. I get this error :
415 Unsupported Media Type. "no mediatypeformatter is available to read an object of type 'harryviewmodel' from content with media type 'application/octet-stream'."
Take a better look at the ERROR :
Thank you so much for your attention.
You are not passing response to the api.
const reponse = {
"Id_Harry" : this.harry.getId,
"x_harry" : this.harry.getX(),
"y_harry" : this.harry.getY(),
"Pv_Harry" : this.harry.getPv(),
"Force_Harry" : this.harry.getForce()
};
// Instead of this.checkResponse, pass "response" which is your post data.**
this.http.post(url, response).toPromise().then((data:any) => {
console.log(data);
console.log(data.json.test);
this.json = JSON.stringify(data.json);
});
And if API is not recognizing post data type, then pass on proper content type header to your post request like this:-
const reponse = {
"Id_Harry" : this.harry.getId,
"x_harry" : this.harry.getX(),
"y_harry" : this.harry.getY(),
"Pv_Harry" : this.harry.getPv(),
"Force_Harry" : this.harry.getForce()
};
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json'
})
};
this.http.post(url, response, httpOptions).toPromise().then((data:any) => {
console.log(data);
console.log(data.json.test);
this.json = JSON.stringify(data.json);
});
You can read more about HttpClient options here
I have checked your code:
Here's what you need to do :
import { HttpHeaders } from '#angular/common/http';
const response = {
"Id_Harry" : this.harry.getId,
"x_harry" : this.harry.getX(),
"y_harry" : this.harry.getY(),
"Pv_Harry" : this.harry.getPv(),
"Force_Harry" : this.harry.getForce()
};
const headers = new HttpHeaders();
headers.append('Content-Type', 'application/json');
headers.append('Accept', 'application/json');
this.http.post(url, response, { headers: headers }).toPromise().then((data:any) => {
console.log(data);
console.log(data.json.test);
this.json = JSON.stringify(data.json);
});
I have an object class and i want to use it in my ASP.NET Core angular project. I can't map the object return through the http get method. Any options please?
class file:
[Serializable]
public class PricesRules
{
public HashSet<Price> Prices { get; set; }
public HashSet<Customer> Customers { get; set; }
public HashSet<Payment> Payments { get; set; }
}
component.ts :
public prices: PricesRules;
constructor(private http: HttpClient, #Inject('BASE_URL') private baseUrl: string) {
http.get<PricesRules>(baseUrl + 'api/UpdatePrices/GetLastPrices').subscribe(result => {
this.prices = result[0];
}, error => console.error(error));
}
interface PricesRules {
Prices: any[];
Customers: any[];
Payments: any[];
}
Controller file:
[HttpGet("[action]")]
public IEnumerable<PricesRules> GetLastPrices()
{
PricesRules pricesRules = null;
//some code here
yield return pricesRules;
}
In my component I have good values in my result object, but my object prices is undefined after.
Edit : Now the get method is ok, but my post method not firing my controller.
component.ts
'''
onClickSubmit(data) {
const params = new HttpParams().set('ID', '1');
const headers = new HttpHeaders().set('content-type', 'application/json');
this.http.post<PricesRules>(this.baseUrl + 'api/UpdatePrices/PostUpdatePrices' + this.prices, { headers, params }).subscribe(result => {
console.log("success");
}, error => console.error(error));
}
'''
Controller
'''
[HttpPost("[action]")]
public async Task<IActionResult> PostUpdatePrices([FromBody] PricesRules pricesRules)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
return null;
}
'''
I have this error :
Object { headers: {…}, status: 404, statusText: "Not Found", url: "https://localhost:44374/api/UpdatePrices/PostUpdatePrices[object%20Object]", ok: false, name: "HttpErrorResponse", message: "Http failure response for https://localhost:44374/api/UpdatePrices/PostUpdatePrices[object%20Object]: 404 Not Found", error: "\n\n\n\nError\n\n\nCannot POST /api/UpdatePrices/PostUpdatePrices%5Bobject%20Object%5D\n\n\n" }
I assume your api return PricesRules instead of IEnumerable<PricesRules>(as you said you get the data).So Because result will be an object like {Prices:[...],...} so you can not access it by index you will need to change
this.prices = result[0];
to
this.prices = result.Prices;
or this.prices = result['Prices'];
I have modify the component.ts
'''
const headers = new HttpHeaders()
.set("Content-Type", "application/json");
this.http.post(this.baseUrl + 'api/UpdatePrices/PostUpdatePrices',
this.prices,
{ headers })
.subscribe(
val => {
console.log("PUT call successful value returned in body",
val);
},
response => {
console.log("PUT call in error", response);
},
() => {
console.log("The PUT observable is now completed.");
}
);
'''
I am sending an id and a list from angular to C# web API, but it is received by null when debugging the method, without knowing the reason.
angular service
this.deletevacs = function (staffid, vacs) {
return $http.post("/AssignUserToDepartmentapi/api/assignuser/deletevacs?staffid=" + staffid + '&vacs=' + JSON.stringify(vacs))
}
angular js
var result = DevExpress.ui.dialog.confirm("Are you sure want to delete vacations assigned employees ?", "Confirm changes");
result.done(function (dialogResult) {
if (dialogResult) {
var promisePost = Assignments.deletevacs($scope.SelectedEmp1.staffkey, $scope.oldvacs);
promisePost.then(function (pl) {
toastr.success("Successfully deleted");
C#
[HttpPost]
public HttpResponseMessage deletevacs(int staffid,int[] vacs)
{
try
{
obj.ExecNonQuery(string.Format("delete from HR_AssRole_Dep where staff_key={0} and Role=7 and Current_Flag=1 and VacMKey ={1}"
, staffid
, vacs));
}
catch (Exception ex)
{
}
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK);
return response;
}
any help, thanks in advance
new C#
[HttpPost]
public HttpResponseMessage deletevacs([FromBody] role r)
{
obj.ExecNonQuery(string.Format("delete from HR_AssRole_Dep where staff_key={0} and Role=7 and Current_Flag=1 and VacMKey ={1}"
,r.Staff_Key
, r.VacMKey));
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK);
return response;
}
class
public class role
{
//public int Ass_Dep_Key { get; set; }
public int Dep_Key { get; set; }
public int Staff_Key { get; set; }
public int Role { get; set; }
public List<int> VacMKey { get; set; }
public short SelfApprov { get; set; }
}
new angular
var deletevacssss = { Staff_Key: $scope.SelectedEmp1.staffkey, VacMKey: $scope.selectedvacs };
var result = DevExpress.ui.dialog.confirm("Are you sure want to delete vacations assigned employees ?", "Confirm changes");
result.done(function (dialogResult) {
if (dialogResult) {
var promisePost = Assignments.deletevacs(deletevacssss);
promisePost.then(function (pl) {
toastr.success("Successfully deleted");
new angular service
this.deletevacs = function (deletes) {
return $http.post("/AssignUserToDepartmentapi/api/assignuser/deletevacs", deletes)
}
when i make a debug, the r object from role class get the staffkey from angular correctly but the list of vacmkey count by 0 ???
you should pass the parameter values for post method in params property .
var data = {staffid: staffid, vacs:vacs};
$http({
url: "/AssignUserToDepartmentapi/api/assignuser/deletevacs",
method: "POST",
params: data
})
or try this below way
var data = {staffid: staffid, vacs:vacs};
$http.post("/AssignUserToDepartmentapi/api/assignuser/deletevacs", data ).then(function (data, status, headers, config) {
alert("success");
},function (data, status, headers, config) {
alert("error");
});
API code should be like
[HttpPost]
public HttpResponseMessage deletevacs([FromUri]int staffid, [FromUri] int[] vacs)
{
...
}
Solution 1:
Use [FromUri] attribute in your HttpPost method parameter since you are getting the value from the querystring in the Url.
Try this:
[HttpPost]
public HttpResponseMessage deletevacs([FromUri]int staffid, [FromUri] int[] vacs)
{
try
{
obj.ExecNonQuery(string.Format("delete from HR_AssRole_Dep where staff_key={0} and Role=7 and Current_Flag=1 and VacMKey ={1}"
, staffid
, vacs));
}
catch (Exception ex)
{
}
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK);
return response;
}
Solution 2:
Create an object that contains the staffId and vacs properties and assign it to the parameter. Add the [FromBody] attribute to before the object parameter. Then in your httpPost call, put the parameter inside the body of the request instead of the Url.
Google about the use of [FromBody] in webapi.
Solution 3:
Istead of using HttpPost, why not use HttpDelete method. It is clear in your problem that your intention is to delete records. In web API, you can use the HttpDelete attribute instead of HttpPost. To do this, change your attribute to HttpDelete from HttpPost, and in your paramter, you can just pass the [FromUri] int StaffId only and inside your API, all the vacs record related that StaffId, you can delete programmatically in DB. When calling your API use the $http.delete endpoint method instead.
I'm trying to upload a form with some text fields and a file to my WebAPI. Currently I always get a 415 error (a breakpoint in the ASP controller doesn't gets hit). My code looks like this:
Angular Service
// 'Upload' is from ng-file-upload
function applicationService(settings, $http, Upload) {
var createCustomApplication = function(application) {
var url = settings.baseUrl + '/api/applications/custom';
var data = new FormData();
angular.forEach(application, function (value, key) {
data.append(key, value);
});
return Upload.upload({
url: url,
data: data,
method: 'POST'
});
};
return {
createCustomApplication: createCustomApplication
}
}
WebAPI controller
[ResponseType(typeof(ApplicationModel))]
[HttpPost, Route("api/applications/custom")]
public IHttpActionResult CreateCustomApplication([FromBody]ApplicationModel application)
{
var file = HttpContext.Current.Request.Files[0];
return Ok();
}
If you want to include a form with files as parameter to an action it is necessary to add a custom media formatter. Fortunately someone already created a Nuget-package for this. Configuration is easy. Install the package and add a line to your WebApiConfig-file.
This package allows you to use a HttpFile-object which captures your file either directly as a parameter or inside a model. From the docs:
[HttpPost]
public void PostFileBindRawFormData(MultipartDataMediaFormatter.Infrastructure.FormData formData)
{
HttpFile file;
formData.TryGetValue(<key>, out file);
}
or
public class PersonModel
{
public string FirstName {get; set;}
public string LastName {get; set;}
public DateTime? BirthDate {get; set;}
public HttpFile AvatarImage {get; set;}
public List<HttpFile> Attachments {get; set;}
public List<PersonModel> ConnectedPersons {get; set;}
}
//api controller example
[HttpPost]
public void PostPerson(PersonModel model)
{
//do something with the model
}
I've had the same issue.
You should add the content type in your POST request.
headers: {
'Content-Type': undefined
},
You're code looks very similar to what I use. Perhaps the issue is to do with the multipart/form-data header value. I'm not experienced enough to say what is wrong in your implementation, but perhaps try this alternate async await approach.
[Route("api/applications/custom")]
[HttpPost]
public async Task<HttpResponseMessage> Upload()
{
MultipartMemoryStreamProvider memoryStreamProvider;
try
{
if (!Request.Content.IsMimeMultipartContent())
{
this.Request.CreateResponse(HttpStatusCode.UnsupportedMediaType);
}
memoryStreamProvider = await Request.Content.ReadAsMultipartAsync();
}
catch (Exception e)
{
return Request.CreateResponse(HttpStatusCode.BadRequest, string.Format("An error has occured while uploading your file. Error details: '{0}'", e.Message));
}
// do something with your file...
return Request.CreateResponse(HttpStatusCode.OK);
}
Here is my JS code. I also use promises instead of what ever is returned (if anything) from the Upload function.
$scope.submit = function() {
if ($scope.form.file.$valid && $scope.file) {
$scope.upload($scope.file);
}
};
$scope.upload = function(file) {
Upload.upload({
url: 'api/applications/custom',
data: { file: file }
}).then(function(response) {
// report the success to the user
}, function(response) {
// report the error to the user
}, function(evt) {
// report the progress of the upload to the user
$scope.uploadProgress = evt.loaded / evt.total;
});
};
I used the following article as a basis for my solution: http://monox.mono-software.com/blog/post/Mono/233/Async-upload-using-angular-file-upload-directive-and-net-WebAPI-service/
I was wondering how I can achieve model validation with ASP.NET Web API. I have my model like so:
public class Enquiry
{
[Key]
public int EnquiryId { get; set; }
[Required]
public DateTime EnquiryDate { get; set; }
[Required]
public string CustomerAccountNumber { get; set; }
[Required]
public string ContactName { get; set; }
}
I then have a Post action in my API Controller:
public void Post(Enquiry enquiry)
{
enquiry.EnquiryDate = DateTime.Now;
context.DaybookEnquiries.Add(enquiry);
context.SaveChanges();
}
How do I add if(ModelState.IsValid) and then handle the error message to pass down to the user?
For separation of concern, I would suggest you use action filter for model validation, so you don't need to care much how to do validation in your api controller:
using System.Net;
using System.Net.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
namespace System.Web.Http.Filters
{
public class ValidationActionFilter : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
var modelState = actionContext.ModelState;
if (!modelState.IsValid)
actionContext.Response = actionContext.Request
.CreateErrorResponse(HttpStatusCode.BadRequest, modelState);
}
}
}
Maybe not what you were looking for, but perhaps nice for someone to know:
If you are using .net Web Api 2 you could just do the following:
if (!ModelState.IsValid)
return BadRequest();
Depending on the model errors, you get this result:
{
Message: "The request is invalid."
ModelState: {
model.PropertyA: [
"The PropertyA field is required."
],
model.PropertyB: [
"The PropertyB field is required."
]
}
}
Like this, for example:
public HttpResponseMessage Post(Person person)
{
if (ModelState.IsValid)
{
PersonDB.Add(person);
return Request.CreateResponse(HttpStatusCode.Created, person);
}
else
{
// the code below should probably be refactored into a GetModelErrors
// method on your BaseApiController or something like that
var errors = new List<string>();
foreach (var state in ModelState)
{
foreach (var error in state.Value.Errors)
{
errors.Add(error.ErrorMessage);
}
}
return Request.CreateResponse(HttpStatusCode.Forbidden, errors);
}
}
This will return a response like this (assuming JSON, but same basic principle for XML):
HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8
(some headers removed here)
["A value is required.","The field First is required.","Some custom errorm essage."]
You can of course construct your error object/list any way you like, for example adding field names, field id's etc.
Even if it's a "one way" Ajax call like a POST of a new entity, you should still return something to the caller - something that indicates whether or not the request was successful. Imagine a site where your user will add some info about themselves via an AJAX POST request. What if the information they have tried to entered isn't valid - how will they know if their Save action was successful or not?
The best way to do this is using Good Old HTTP Status Codes like 200 OK and so on. That way your JavaScript can properly handle failures using the correct callbacks (error, success etc).
Here's a nice tutorial on a more advanced version of this method, using an ActionFilter and jQuery: http://asp.net/web-api/videos/getting-started/custom-validation
Or, if you are looking for simple collection of errors for your apps.. here is my implementation of this:
public override void OnActionExecuting(HttpActionContext actionContext)
{
var modelState = actionContext.ModelState;
if (!modelState.IsValid)
{
var errors = new List<string>();
foreach (var state in modelState)
{
foreach (var error in state.Value.Errors)
{
errors.Add(error.ErrorMessage);
}
}
var response = new { errors = errors };
actionContext.Response = actionContext.Request
.CreateResponse(HttpStatusCode.BadRequest, response, JsonMediaTypeFormatter.DefaultMediaType);
}
}
Error Message Response will look like:
{
"errors": [
"Please enter a valid phone number (7+ more digits)",
"Please enter a valid e-mail address"
]
}
You can use attributes from the System.ComponentModel.DataAnnotations namespace to set validation rules. Refer Model Validation - By Mike Wasson for details.
Also refer video ASP.NET Web API, Part 5: Custom Validation - Jon Galloway
Other References
Take a Walk on the Client Side with WebAPI and WebForms
How ASP.NET Web API binds HTTP messages to domain models, and how to work with media formats in Web API.
Dominick Baier - Securing ASP.NET Web APIs
Hooking AngularJS validation to ASP.NET Web API Validation
Displaying ModelState Errors with AngularJS in ASP.NET MVC
How to render errors to client? AngularJS/WebApi ModelState
Dependency-Injected Validation in Web API
Add below code in startup.cs file
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2).ConfigureApiBehaviorOptions(options =>
{
options.InvalidModelStateResponseFactory = (context) =>
{
var errors = context.ModelState.Values.SelectMany(x => x.Errors.Select(p => new ErrorModel()
{
ErrorCode = ((int)HttpStatusCode.BadRequest).ToString(CultureInfo.CurrentCulture),
ErrorMessage = p.ErrorMessage,
ServerErrorMessage = string.Empty
})).ToList();
var result = new BaseResponse
{
Error = errors,
ResponseCode = (int)HttpStatusCode.BadRequest,
ResponseMessage = ResponseMessageConstants.VALIDATIONFAIL,
};
return new BadRequestObjectResult(result);
};
});
C#
public class ValidateModelAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
if (actionContext.ModelState.IsValid == false)
{
actionContext.Response = actionContext.Request.CreateErrorResponse(
HttpStatusCode.BadRequest, actionContext.ModelState);
}
}
}
...
[ValidateModel]
public HttpResponseMessage Post([FromBody]AnyModel model)
{
Javascript
$.ajax({
type: "POST",
url: "/api/xxxxx",
async: 'false',
contentType: "application/json; charset=utf-8",
data: JSON.stringify(data),
error: function (xhr, status, err) {
if (xhr.status == 400) {
DisplayModelStateErrors(xhr.responseJSON.ModelState);
}
},
....
function DisplayModelStateErrors(modelState) {
var message = "";
var propStrings = Object.keys(modelState);
$.each(propStrings, function (i, propString) {
var propErrors = modelState[propString];
$.each(propErrors, function (j, propError) {
message += propError;
});
message += "\n";
});
alert(message);
};
Here you can check to show the model state error one by one
public HttpResponseMessage CertificateUpload(employeeModel emp)
{
if (!ModelState.IsValid)
{
string errordetails = "";
var errors = new List<string>();
foreach (var state in ModelState)
{
foreach (var error in state.Value.Errors)
{
string p = error.ErrorMessage;
errordetails = errordetails + error.ErrorMessage;
}
}
Dictionary<string, object> dict = new Dictionary<string, object>();
dict.Add("error", errordetails);
return Request.CreateResponse(HttpStatusCode.BadRequest, dict);
}
else
{
//do something
}
}
}
I had an issue implementing the accepted solution pattern where my ModelStateFilter would always return false (and subsequently a 400) for actionContext.ModelState.IsValid for certain model objects:
public class ModelStateFilter : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
if (!actionContext.ModelState.IsValid)
{
actionContext.Response = new HttpResponseMessage { StatusCode = HttpStatusCode.BadRequest};
}
}
}
I only accept JSON, so I implemented a custom model binder class:
public class AddressModelBinder : System.Web.Http.ModelBinding.IModelBinder
{
public bool BindModel(HttpActionContext actionContext, System.Web.Http.ModelBinding.ModelBindingContext bindingContext)
{
var posted = actionContext.Request.Content.ReadAsStringAsync().Result;
AddressDTO address = JsonConvert.DeserializeObject<AddressDTO>(posted);
if (address != null)
{
// moar val here
bindingContext.Model = address;
return true;
}
return false;
}
}
Which I register directly after my model via
config.BindParameter(typeof(AddressDTO), new AddressModelBinder());
You can also throw exceptions as documented here:
http://blogs.msdn.com/b/youssefm/archive/2012/06/28/error-handling-in-asp-net-webapi.aspx
Note, to do what that article suggests, remember to include System.Net.Http
Put this in the startup.cs file
services.AddMvc().ConfigureApiBehaviorOptions(options =>
{
options.InvalidModelStateResponseFactory = (context) =>
{
var errors = context.ModelState.Values.SelectMany(x => x.Errors.Select(p =>p.ErrorMessage)).ToList();
var result = new Response
{
Succeeded = false,
ResponseMessage = string.Join(", ",errors)
};
return new BadRequestObjectResult(result);
};
});