I added a IOperationFilter to swagger so that I can test file uploads for my apis from swagger ui. My Dto is like;
public class ResourceCreateDto : EntityDto
{
public string Title { get; set; }
public string Description { get; set; }
public IFormFile File { get; set; } //file content here
public string ExtendedData { get; set; }
}
Asp.net Core API is:
public async Task<ResourceDto> Create([FromForm] ResourceCreateDto input)
This way I can upload file & other data at the same time (Some have suggested to save file 1st and then save data in another call).
What I am not sure is how to use it in Angular end with Abp. Even though proxies are generated how can I get the angular client to use [File] property and post it's data with the rest to server api?
create DTO:
export class ResourceCreateDto{
title : String;
description: String;
extendedData : String;
file: File;
}
in html
<input class="form-control" type="text" [(ngModel)]="resourceCreateDto.title"/>
<input class="form-control" type="text" [(ngModel)]="resourceCreateDto.description"/>
<input class="form-control" type="file" [(ngModel)]="resourceCreateDto.extendedData"/>
<input class="form-control" type="text" [(ngModel)]="resourceCreateDto.file" (change)="onChangeFile($event)"/>
<button class="btn btn-primary" type="button" (click)="submit()"> Add new </button>
in component
resourceCreateDto: ResourceCreateDto;
file: any;
ngOnInit(): void {
//..
resourceCreateDto = new ResourceCreateDto();
}
onChangeFile(event){
this.file = event.srcElement.files;
}
submit(){
let formData: FormData = new FormData();
formData.append('title', this.resourceCreateDto.title + '');
formData.append('description', this.resourceCreateDto.description + '');
formData.append('extendedData', this.resourceCreateDto.extendedData + '');
formData.append('file', this.file[0], this.file[0].name);
// use service call api
// declare your httpClient
this.httpClient.post<httpResponse>(`${this.BASEURL}/...`, formData,
this.getHttpFileOptions(your token))
.subscribe(response =>{
console.log(response);
},
error=>{
console.log(error);
})
}
setting option http
getHttpFileOptions(token: String): object{
return {
observe: 'response',
responseType: 'json',
headers: new HttpHeaders({
"Accept": "application/json",
'Authorization': 'Bearer ' + token
})
};
}
action in server
[HttpPost("Create")]
public IActionResult Create([FromForm]ResourceCreateDto model, IFormFile File)
Hope to help you!
Related
I need to send an ajax request to a post method defined in my asp.net core web api as below :
// POST: api/Entreprise/Inscription
[HttpPost("Inscription")]
public IActionResult Post([FromBody] UserInfos value)
{
return Ok("value 1");
}
and this is UserInfos model:
public class UserInfos
{
public string firstname { get; set; }
public string lastname { get; set; }
public string email { get; set; }
public string domainName { get; set; }
public string phoneNumber {get;set;}
public string address { get; set; }
public string city { get; set; }
public string zip_code { get; set; }
}
I tested it with postman , by setting the header as 'Content-Type':'application/json' and in the body choosed raw and passed this json object :
{
"firstname" :"ahmed",
"lastname":"haddad",
"email":"haddad-a#live.fr" ,
"domainName":"easyappointments-master" ,
"phoneNumber":"25276164",
"address":"ariana" ,
"city":"grand tunis",
"zip_code":"4100"
}
and i get it to work, however when i call it from ajax i get BAD REQUEST 400 , this is my ajax code:
var newData={
"firstname" :"ahmed",
"lastname":"haddad",
"email":"haddad-a#live.fr" ,
"domainName":"easyappointments-master" ,
"phoneNumber":"25276164",
"address":"ariana" ,
"city":"grand tunis",
"zip_code":"4100" ,
};
var dataJson= JSON.stringify(newData);
$.ajax({
url:'http://test.example.fr/wsexample/api/Entreprise/Inscription',
dataType:'json',
data:dataJson,
ContentType:'application/json',
type:'post',
success:function(data,status){
console.log('the request is '+status+' the data is '+data);
},
error:function(html,status,error){
console.log('the request is '+error);
}
});
Note: the asp.net core web api and the ajax codes are in different servers ,so different domains , i have enabled the access to CORS for my domain in startup.cs , so normally that shouldn't trigger an issue.
also i have made succeded get requests to that webservice
I think the error has to do with your
ContentType:'application/json',
It should be
contentType: 'application/json',
and also remove this
dataType: "json"
jQuery.ajax attempts to convert the response body depending on the specified dataType parameter or the Content-Type header sent by the server. If the conversion fails (e.g. if the JSON/XML is invalid), the error callback is fired. Read more here: Ajax request returns 200 OK, but an error event is fired instead of success
I got this to work:
EnterpriseController.cs
public class EnterpriseController : Controller
{
public async Task<IActionResult> Index()
{
return View();
}
[HttpPost]
[Route("api/[controller]/Inscription")]
public IActionResult Post([FromBody] UserInfos value)
{
return Ok("value 1");
}
}
Index.cshtml
#section Scripts {
<script>
$(document).ready(function () {
var newData = {
"firstname": "ahmed",
"lastname": "haddad",
"email": "haddad-a#live.fr",
"domainName": "easyappointments-master",
"phoneNumber": "25276164",
"address": "ariana",
"city": "grand tunis",
"zip_code": "4100"
}
$.ajax({
url: '/api/Enterprise/Inscription/',
type: 'POST',
contentType: 'application/json',
data: JSON.stringify(newData),
success: function (data, status) {
console.log('the request is ' + status + ' the data is ' + data);
},
error: function (html, status, error) {
console.log('the request is ' + error);
}
});
});
</script>
}
Console:
the request is success the data is value 1
removing [FromBody] from the controller
2.below the controller class use this [ApiController]
3.use this for post
$.ajax({
url:'http://test.example.fr/wsexample/api/Entreprise/Inscription',
data:JSON.stringify({
"firstname" :"ahmed",
"lastname":"haddad",
"email":"haddad-a#live.fr" ,
"domainName":"easyappointments-master" ,
"phoneNumber":"25276164",
"address":"ariana" ,
"city":"grand tunis",
"zip_code":"4100" ,
}),
type:'post',
headers: {
'Content-Type': 'application/json'
},
success:function(data,status){
console.log('the request is '+status+' the data is '+data);
},
error:function(html,status,error){
console.log('the request is '+error);
}
});
4.put [IgnoreAntiforgeryToken] top of your actionresult
I'm developing a web application using Asp.Net Core Razor Pages.On the page model I have the following property:
public class SchoolModel : PageModel
{
[BindProperty]
public School SchoolEdit { get; set; }
I'd like to change the Logo property of SchoolEdit(of type School) when I click a button on the form without having the form posted.How can I accomplish this?
Here's the razor page code:
#if (Model.SchoolEdit.Logo != null)
{
<button class="btn btn-danger" asp-page-handler="RemovePhoto">
<span aria-hidden="true">×</span>
</button>
}
Later,I defined the following Ajax to change the property when the button is clicked,but the OnPostRemovePhoto doesn't get hit!
#section Scripts {
<script>
$(function () {
$("#Click").click(function () {
$.ajax({
type: "POST",
url: "./School?handler=RemovePhoto",
error: function (response) {
alert('hi');
},
success: function (response) {
alert('error');
}
});
});
})
</script>
Thanks to the same thread on Asp.Net,I figured out the issue.
The anti-forgery token was missing.The AJAX method below sets the token in the header.
Here's the answer:
I am trying to submit some data and file to my controller's action:
[HttpPost]
public ActionResult Settle(SettlePrepaymentViewModel settlePrepaymentViewModel)
{
//Do something and return JSON
}
My view model contains the following properties:
public HttpPostedFileBase File { get; set; }
public Guid? PrepaymentId { get; set; }
In my form I have some textboxes and a file input. When I press button, I want my form (with file) to be submitted to my action:
$('#btnConfirmSettlement').click(function (e) {
$.ajax({
url: '#Url.Action("Settle", "Prepayments")',
type: "POST",
data: $("#uploadFile").serialize(),
success: function (data) {
if (data.isSuccess) {
toastr.success("Success");
} else {
toastr.error(data.errorMessage);
}
},
error: function (data) {
toastr.error(data.errorMessage);
}
});
return false;
});
However when using the above code it does not work (there is no file passed to my action. However when using the following code (where my form is simply submitted) it works fine:
#using (Html.BeginForm("Settle", "Prepayments", FormMethod.Post, new {enctype = "multipart/form-data", #id="uploadFileSubmi"}))
{
#Html.TextBoxFor(model => model.SettlePrepaymentViewModel.File, new {type = "file"})
<input type="submit" value="Settle"/>
}
I was trying to use form submit when I click "Save" on my twitter bootstrap modal but then it just returns me (redirects me to) a JSON result from my action - I don't want to be redirected. Can someone please help me with this? What am I doing wrong?
Can somebody help me how can I post model back to controller using jQuery and ajax.
When I post my form, my controller is receiving an empty model. Please corrent me where I am doing a mistake.
Model:
public class AllocateToStore
{
public IList<OrderLine> FailureAllocations { get; set; }
public IList<SelectListItem> AllocationStatus
{
get
{
// code to fetch list.
}
}
}
public class OrderLine
{
public long Id { get; set; }
public DateTime Date { get; set; }
public int Status { get; set; }
}
Controller:
public ActionResult AutoAllocate()
{
// This action will load the view with data.
// Get model data and send it to view.
return View("Allocated",model);
}
[HttpPost]
public ActionResult ResolveUnallocatedOrders(AllocateToStore coll)
{
// When user changes the selection in grid and post the page I need to get the selection // here. So that I can update that record.
return null;
}
And view is
#model AllocateToStore
#{
ViewBag.Title = "Orders";
}
#{
var grid = new WebGrid(Model.FailureAllocations, rowsPerPage: 100);
}
if (Model.FailureAllocations.Any())
{
<form>
<div>
#grid.GetHtml(
columns: grid.Columns(
grid.Column(columnName: "Order date", header: "Order Date", format: item => item.Order.Date),
grid.Column("dropdown", header: "Resolution", format:
#<span>
#{ var index = Guid.NewGuid().ToString(); }
#Html.Hidden("FailureAllocations.Index", index)
#Html.Hidden("FailureAllocations[" + index + "].Id", (long)item.Id)
#Html.DropDownList("FailureAllocations[" + index + "].Status", new SelectList(Model.AllocationStatus, "Value", "Text", item.Status))
</span>
)
),
tableStyle: "expandable-table",
htmlAttributes: new { id = "gridFailureAllocations" }
)
<br />
<input type="submit" value="Resolve" id="resolve-button" />
</div>
</form>
}
#section scripts
{
<script>
$("#resolve-button").click(function () {
debugger;
alert("here");
$.ajax({
url: '/OrderProcessing/ResolveUnallocatedOrders',
data: $('#form').serialize(),
type: 'POST'
});
});
</script>
}
Thanks,
Naresh
i did not test this answer .it is just suggestion . please try this way.
$.ajax({
url: o.url,
type: 'post',
contentType: "application/x-www-form-urlencoded",
data: {"FailureAllocations ":JSON.stringify(FailureAllocations), "AllocationStatus":JSON.stringify(AllocationStatus)}',
. . . .
});
I think you have a bug here data: $('#form').serialize(),
$('#form') will select all elements with the id "form". You form doesn't have an id, so your selector won't be working. Try changing that line to data: $('form').serialize(), and the selector should work.
Alternatively, give your form an id of "form" e.g. <form id="form"> and the original selector $('#form') should work.
See here for more details on the various jQuery selectors.
I have been working with MVC for the past few days.
I have a problem in one of my pages, i.e I have a page where q user enters the required details and uploads a file. I have two buttons named Upload for Uploading File and Create for creating new profile.
My Problem
My problem is I don't want to reload the whole page when user clicks on upload button. I was thinking of using an webmethod for fileupload.
I don't know if what am I doing wrong here
Can any one correct me
This is my Webmethod in my controller named Create
Controller
[WebMethod]
public string FileUpload(HttpPostedFileBase file, BugModel model)
{
BugModel bug = null;
if (file != null && file.ContentLength > 0)
{
string path = "/Content/UploadedFiles/" + Path.GetFileName(file.FileName);
string savedFileName = Path.Combine(System.Web.HttpContext.Current.Server.MapPath ("~" +path));
file.SaveAs(savedFileName);
BugAttachment attachment = new BugAttachment();
attachment.FileName = "~" + path.ToString();
bug.ListFile.Add(attachment);
model = bug;
}
return "FileUploaded";
}
used a script to call the method
Javascript
<script type="text/javascript">
function UploadFile() {
$.ajax({
type:"Post",
url: "LogABug/FileUpload",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
alert("File Uploaded")
},
error: function () {
ErrorMessage("Try Again");
}
});
}
</script>
can any one tell me how can I do this ...if this is the wrong method correct me the right one with the ideas please
You are uploading the file separately. Therefore you will need two actions:
public string Something(BugModel model) for the model.
public string FileUpload(HttpPostedFileBase file) for the file
Now, I would use jQuery Form Plugin for ajax submitting. Here is an example:
<script type="text/javascript">
$(function () {
$("#file-upload-form").submit(function () {
$(this).ajaxSubmit({
target: "#message",
cache: false
});
return false;
});
});
</script>
#using(Html.BeginForm("FileUpload", "LogABug", FormMethod.Post, new { enctype = "multipart/form-data", id = "file-upload-form" })) {
#Html.ValidationSummary(true)
<fieldset>
#Html.EditorFor(model => model.File)
<input type="submit" value="Upload" />
</fieldset>
}
<div id="message">
</div>
What ever you return from your action will be displayed in the div with id message