I'm trying to submit a form from angularjs controller as $http.post() to asp.net web api method. But it sends null value. Here is my code
//angular controller
$scope.newpost = {};
$scope.save = function () {
console.log($scope.newpost); // it logs data accurately
$http.post('/api/NewPost', $scope.newpost).
success(function (data, status, headers, config) {
alert("ok");
});
}
//api
public HttpResponseMessage post(NewPost newpost) //fields are null here. I tried [FromBody] $ [FromURI], but no luck
{
posts.Add(newpost);
String id = newpost.Id; //saving is ok.
return Request.CreateResponse(HttpStatusCode.OK);
}
//model
public class NewPost
{
public String Title { get; set; }
public String Content { get; set; }
public String Tags { get; set; }
}
console.log($scope.newpost) displays-
Object {Title: "t", Content: "tt", Tags: "ttt"}
Any help?
use this:
console.log($scope.newpost.Title ); // it should logs data accurately
console.log($scope.newpost.Content );// it should logs data accurately
console.log($scope.newpost.Tags );// it should logs data accurately
$http.post('/api/NewPost', $scope.newpost).
success(function (data, status, headers, config) {
alert("ok");
});
Related
const [payload, setPayload] = useState({
Email: null,
Password: null
});
const handleSubmit = async (e) => {
e.preventDefault();
var json = JSON.stringify(payload);
try {
const { data } = await axios.post(
"https://localhost:5001/api/User/Login",
{
json
}
);
console.log(data);
ctxDispatch({ type: "USER_LOGIN", payload: data });
localStorage.setItem("userInfo", JSON.stringify(data));
toast.success("Login Successful");
navigate("/");
} catch (err) {
toast.error(getError(err));
}
};
[AllowAnonymous]
[HttpPost("Login")]
public async Task<ActionResult<UserDTO>> Login([FromBody] LoginDTO loginDTO)
{
//LoginDTO loginDTO = Newtonsoft.Json.JsonConvert.DeserializeObject<LoginDTO>(input);
var pwd = Encrypt.ConvertToEncrypt(loginDTO.Password);
User currentUser = await _context.user.FirstOrDefaultAsync(user =>
user.Email.ToLower() == loginDTO.Email.ToLower()
&&`enter code here`
user.Password == pwd);
}
public class LoginDTO
{
public string Email { get; set; }
public string Password { get; set; }
}
When I post this string to my backend it attempts to parse my string but fails at the first char {. When i send this string wrapped in quotes through swagger it passes with no issues. When i send this string through postman with no quotes wrapped around the string I get the same exact error as i get when posting through my frontend.
fix the action input parameters, you don't need to deserialize it , it will be deserialized by MVC
public async Task< ....([FromBody] LoginDTO loginDto)
and since you are sending a json string, add content type to axios
axios.post('..your url', json, {
headers: {
// Overwrite Axios's automatically set Content-Type
'Content-Type': 'application/json'
}
});
I have a file uploader component in angular that posts a file and a json object string to a web api controller. unfortunately the values on the server are always null.
Here is the angular method used for upload :
public upload(event: any): void {
const file = event.target.files[0];
const formData = new FormData();
var product = {
productCode: '009',
productName: 'Test Product Name',
clientKey: '616f1d97-6798-459a-957f-6e6476aa3c82',
providerId: 1
};
formData.append('file', file, file.name);
formData.append('body', JSON.stringify(product));
var headers = { headers:{
'Content-Type': 'application/json',
'TimeStamp' : '2022-05-05T16:50:36'
}}
this.http.post('http://localhost:9913/api/internal/testProduct/Add', formData, headers)
.pipe(
map(res => console.log('got response', res),
catchError(error => of(console.error('got error', error)))))
.subscribe(() => console.log('next'), error => console.log(error));
}
And the web api controller method:
[HttpPost("Add")]
public async Task<IActionResult> AddProduct([FromForm] AddProductEntity addProductEntity)
{
ProductRequestContract addNewProductRequestContract = new ProductRequestContract();
var requestObj = JsonConvert.DeserializeObject<ProductRequestContract>(addProductEntity.body);
if (requestObj == null)
{
return base.BadRequest("Not valid product");
}
#region upload file to temp folder
if (addProductEntity.file != null)
{
var uploadFileResult = SaveImage(addProductEntity.file);
if (!uploadFileResult)
{
return BadRequest("Error saving the file.");
}
}
#endregion
return Ok();
}
the parameter AddProductEntity addProductEntity are always null, why web api model binder is unable to match form data sent in the request?
Note: AddProductEntity is a simple DTO class has 2 props which matches the form data values:
public class AddProductEntity
{
public IFormFile file { get; set; }
public string body { get; set; }
}
I have function in a C# controller file that makes an API call to fetch some placeholder data that is hard coded locally.
[Route("api/ReportingCenter/GetReportList")]
[HttpGet]
public class ReportController : ApiController
{
public async Task<IHttpActionResult> GetReportList(CancellationToken cancellationToken)
{
using (var source = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken,
HttpContext.Current.Response.ClientDisconnectedToken))
{
var userId = 11;
var projId = 22;
using (var reportDb = new ReportDb(userId, projId))
{
var list = reportDb.GetReports(userId, projId);
return Json(list);
}
}
}
}
public class ReportDb : PortalDb
{
public List<ReportInfo> GetReports(int userid, int projectid)
{
var ReportList = new List<ReportInfo>();
ReportList.Add(new ReportInfo(1,"file1.pdf", 11, "a file with data in it", 11112222,"pdf", 1, "22"));
}
}
I coded a button and a function with an aspx file that should make an axios call to run the GetReportList function from the controller. When the button is click, nothing happens. Any suggestions on how to make it so that the API call is made when the button is clicked in the aspx file?
<asp:Content ID="Content5" ContentPlaceHolderID="primaryContent" runat="server">
<div id="reporting-app-container">
<input type="button" value="ReportInfo" class="btn btn-sm btn primary"
onclick="getReportInfo"/>
</div>
<script src="/ReportsModule/app/dist/reporting-app-bundle.js"></script>
<script type="text/javascript">
$(document).ready(function () {
window.ReportingApp();
});
async function getReportInfo(id) {
console.log("pre-axios call")
const response = await axios.get("api/ReportingCenter/GetReportList")
.then(function (response) {
// handle success
console.log(response);
})
.catch(function (error) {
// handle error
console.log(error);
});
}
</script>
</asp:Content>
.then and .catch are methods of a Promise, which is what you'd get if you called axios.get without awaiting it. A Promise represents an action which you've started in the background, which may or may not have finished yet, and which can call callback functions supplied by you if/when it completes successfully or throws an error. Or at least that's a very short description of what it is.
To pass your callback functions to the Promise returned by axios.get, remove the async and await, a bit like this:
function getReportInfo(id) {
axios.get('api/ReportingCenter/GetReportList')
.then(function (response) {
// handle success
console.log(response);
})
.catch(function (error) {
// handle error
console.log(error);
})
.then(function () {
// always executed
});
}
If you want response to be the actual response from the API, rather than a Promise to give you the actual response once the web request has completed, then you can await the Promise, a bit like this:
async function getReportInfo(id) {
try {
const response = await axios.get('api/ReportingCenter/GetReportList');
console.log(response);
} catch (error) {
console.error(error);
}
}
A note of caution if you choose the second option - are you sure all your users' browsers support ECMAScript 2017? If not then the await / async approach probably isn't a good idea and you should stick with the first option.
Code snippets are adapted from this bit of the axios API documentation
Moved the javascript function that handles the axios call into reporting-app.js. Vue is being used on top of javascript. The .aspx file and the Vue app are connected by the "el" key, with the value set to the html id: '#reporting-app-container".
.aspx file
<div>HELLO WORLD!</div>
<div id="reporting-app-container">
<input type="button" value="ReportInfo" class="btn btn-sm btn primary" #click="getReportInfo" />
</div>
<script src="/ReportsModule/app/dist/reporting-app-bundle.js"></script>
.js file
import Vue from 'vue';
window.ReportingApp = function () {
new Vue({
el: '#reporting-app-container',
//store: FilesStore,
data: {},
components: {
'reporting-component': reporting_component,
'list-reports-component': list_report_component
},
methods: {
getReportInfo: function (id) {
console.log("pre-axios call");
axios.get("/api/ReportingCenter/GetReportList")
.then(function (response) {
// handle success
console.log(response);
})
.catch(function (error) {
// handle error
console.log(error);
});
}
}
});
}
The javascript and the C# Controller file are linked by the axios method within the methods section of the Vue app.
Controller.cs
using ###.###.###.api.Models;
namespace ###.###.ReportsModule.api
{
public class ReportController : ApiController
{
protected readonly IPortalStateService PortalState;
public ReportController(IPortalStateService portalStateService)
{
PortalState = portalStateService;
}
[Route("api/ReportingCenter/GetReportList")]
[HttpGet]
public IHttpActionResult GetReportList(CancellationToken cancellationToken)
{
using (var source = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken,
HttpContext.Current.Response.ClientDisconnectedToken))
{
var user = PortalState.GetUserId();
if (user == null)
{
return BadRequest("User is not allowed");
}
var userId = 11;
var projId = 22;
try
{
using (var reportDb = new ReportDb(userId, projId))
{
var list = reportDb.GetReports(userId, projId);
return Json(list);
}
}
catch (Exception e)
{
return Json(e);
}
}
}
}
public class ReportDb : PortalDb
{
public List<ReportInfo> GetReports(int userid, int projectid)
{
var ReportList = new List<ReportInfo>();
ReportList.Add(new ReportInfo(1, "file1.pdf", 11, "a file with data in it",
11112222, "pdf", 1, "22"));
return ReportList;
}
}
}
GetReports function uses the model from ReportInfo.cs that defines the field values and the constructor for the data.
ReportInfo.cs Model
namespace ###.###.reportsmodule.api.Models
{
public class ReportInfo
{
public long Id { get; set; }
public string Name { get; set; }
public int Ordinal { get; set; }
public string Description { get; set; }
public int ProjectId { get; set; }
public string SourceType { get; set; }
public int MinPermissionLevel { get; set; }
public string SourceId { get; set; }
public ReportInfo(long id, string name, int ordinal, string description,
int projectId, string sourceType, int minPermissionLevel, string sourceId)
{
Id = id;
Name = name;
Ordinal = ordinal;
Description = description;
ProjectId = projectId;
SourceType = sourceType;
MinPermissionLevel = minPermissionLevel;
SourceId = sourceId;
}
}
}
I am trying to post data from Angular side to .Net and I'm not hits the breakpoint at Controller c#.
Do I need some configuration? I have already sent data in this way in Angular 8 before and it was working.
c#
public class UpdateViewModel
{
public int Id { get; set; }
public string Title { get; set; }
}
[HttpPost]
[Route("delete")]
public void delete(UpdateViewModel model)
{
//return Ok();
}
ts
var model = {
Id: 1,
Title: 'test'
}
return this.http.post(this.baseURL + "home/delete/", model)
.pipe(
retry(1),
catchError(this.errorHandler)
);
the http client of angular is based on observables. This means, the request will only be sent if you subscribe to the observable. You can do this with .subscribe()or with .toPromise().
For your code:
return this.http.post(this.baseURL + "home/delete/", model)
.pipe(
retry(1),
)
.subscribe({
error: this.errorHandler
});
This is my first asp.net core app, so I'm probably missing something obvious, but I've looked through the other StackOverflow answers, and the solutions there haven't helped me. I have an asp.net core mvc app that I'm running on service fabric, and I'm trying to post a string to a controller. The string is originally an array of json objects.
My ajax post:
var sendThis = { "operations": JSON.stringify(operations) };
$.ajax({
url: '/Home/Execute',
type: 'POST',
data: sendThis,
dataType: "json",
contentType: 'application/json; charset=utf-8',
error: function (xhr) {
$("#save-footer-text").val("Saving failed. Please contact an administrator");
},
success: function (result) {
$(".save-footer").addClass("slider");
},
async: true
});
My controller on the other side. I took the stream stuff from another stack overflow answer, but it just returns an empty string when it's done.
[HttpPost]
public IActionResult Execute([FromBody] string operations /*this is null*/)
{
var i = 5;
string documentContents; //this will be an empty string.
Request.Body.Position = 0;
using (Stream receiveStream = Request.Body)
{
using (StreamReader readStream = new StreamReader(receiveStream, Encoding.Unicode))
{
documentContents = readStream.ReadToEnd();
}
}
Console.WriteLine(i);
return new OkResult();
}
From the other stackoverflow answers, I've also tried posting with traditional set to to true, and I've tried posting operations into a model, like this
public class M
{
public string status { get; set; }
public string appName { get; set; }
public string startTime { get; set; }
public string endTime { get; set; }
public string description { get; set; }
public string operation { get; set; }
}
with the controller changed to public IActionResult Execute([FromBody] List<M> operations)
I've checked that my javascript does send a request, with Chrome tools reporting that the Request payload is:
operations= my json string here
I also see this in Fiddler, so I know it is going over the wire.
Per this answer, I've also tried updating JsonSettings, but that didn't help either.
I'm using 1.0.0-rc2-final for the asp.net core package, and 5.1.150 for service fabric.
What am I missing here? Sorry if the answer is really trivial. Thank you for any help.
If the operations variable in the script is an array
var operations = new Array();
var op1 = { status: 's1', appName: 'a1', startTime: 'st1', endTime: 'e1', description: 'd1', operation: 'o1' };
operations.push(op1);
var op2 = { status: 's2', appName: 'a2', startTime: 'st2', endTime: 'e2', description: 'd21', operation: 'o2' };
operations.push(op2);
var sendThis = JSON.stringify(operations);
...// ajax call here
And the controller post method is defined as follows then List<M> operations should contain the values sent over the wire as expected.
[HttpPost]
public IActionResult Execute([FromBody]List<M> operations)
{
// ... some code here
return Json("");
}
It is a list of M?
If it is, then your json shouldn't be like this
var sendThis = { "operations": JSON.stringify(operations) };
try this:
var sendThis = JSON.stringify(operations);
I think asp.net is trying to deserialize an object like this one:
public class Operation
{
public List<M> Operations { get; set; }
}