Fetch api status is 200 but not showing data [duplicate] - javascript

I have a Controller with the following method:
public void ExportList()
{
var out = GenExport();
CsvExport<LiveViewListe> csv = new CsvExport<LiveViewListe>(out);
Response.Write(csv.Export());
}
this should generate a csv file which the user can download.
I call this method via a jQuery request in my view:
$.getJSON('../Controller2/ExportList', function (data) {
//...
});
the problem is, that I don't get any download and I don't know why. The method is called but without a download.
What is wrong here?

Your controller methods need to always return an ActionResult. So the method should look more like
public ActionResult ExportList()
{
var export = GenExport();
CsvExport<LiveViewListe> csv = new CsvExport<LiveViewListe>(export);
return new CsvResult(csv);
}
Where CsvResult is a class inheriting from ActionResult and doing the necessary to prompt the user for download of your Csv results.
For example, if you really need to Response.Write this could be:
public class CsvResult : ActionResult
{
private CsvExport<LiveViewListe> data;
public CsvResult (CsvExport<LiveViewListe> data)
{
this.data = data;
}
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
HttpResponseBase response = context.HttpContext.Response;
response.ContentType = "text/csv";
response.AddHeader("Content-Disposition", "attachment; filename=file.csv"));
if (data!= null)
{
response.Write(data.Export());
}
}
}
You could also think about making this more generic, if your CsvExport class has the Export method:
public class CsvResult<T> : ActionResult
{
private CsvExport<T> data;
public CsvResult (CsvExport<T> data)
{
this.data = data;
}
.... same ExecuteResult code
}
Now it supports any of your csv downloads, not just LiveViewListe.

Related

How to pass extra parameter with JQuery Dropzone to my java controller method

I have a dropzone function to upload pdf files and receive it in my controller method to process and save in database, but i need to pass an extra parameter which is the value from a select, i already pass it but i receive "null" value in controller method.
this is mi JQuery dropzone method:
...
$("div#uploadFile").dropzone({
url: "/demo/uploadFile"
,params: {
name: $( "#selectedName" ).val()
}
,acceptedFiles: ".pdf"
,clickable: false
,maxFilesize: 100
,addRemoveLinks: true
,init: function() {
this.on('addedfile', function(file) {
//i can see the value in alert
alert($( "#selectedName" ).val());
});
this.on('success', function(file, json) {
alert("ok");
});
});
the controller method (trying to receive in requestParam):
#RequestMapping(value = "/uploadFile", method = RequestMethod.POST)
public ResponseEntity<?> uploadFile( #RequestParam("name") String name, MultipartFile file) {
//here print parameter and is NULL
System.out.println("My extra param received is : "+ name);
//process the file-pdf
...
....
}
Any idea? thanks in advance!
Can you try:
$("div#uploadFile").dropzone({
url: "/demo/uploadFile"
,acceptedFiles: ".pdf"
,clickable: false
,maxFilesize: 100
,addRemoveLinks: true
,init: function() {
this.on('addedfile', function(file) {
//i can see the value in alert
alert($( "#selectedName" ).val());
});
this.on("sending", function(file, xhr, formData) {
formData.append("name", $( "#selectedName" ).val());
console.log(formData);
});
this.on('success', function(file, json) {
alert("ok");
});
});
You can convert any file to byte array on JS side and decode it in java side, so you can send byte array instead of file. Use something like this on your JS side (You should add promises to this JS method):
function getBufferArray(file) {
var fr = new FileReader();
fr.readAsArrayBuffer(file);
return new Uint8Array(fr.result);
}
And on your java side:
public class BASE64DecodedMultipartFile implements MultipartFile {
private final byte[] imgContent;
public BASE64DecodedMultipartFile(byte[] imgContent) {
this.imgContent = imgContent;
}
#Override
public String getName() {
// TODO - implementation depends on your requirements
return null;
}
#Override
public String getOriginalFilename() {
// TODO - implementation depends on your requirements
return null;
}
#Override
public String getContentType() {
// TODO - implementation depends on your requirements
return null;
}
#Override
public boolean isEmpty() {
return imgContent == null || imgContent.length == 0;
}
#Override
public long getSize() {
return imgContent.length;
}
#Override
public byte[] getBytes() throws IOException {
return imgContent;
}
#Override
public InputStream getInputStream() throws IOException {
return new ByteArrayInputStream(imgContent);
}
#Override
public void transferTo(File dest) throws IOException, IllegalStateException {
new FileOutputStream(dest).write(imgContent);
}
}
For pharameters try adding to your dropzone:
params: {
new_value: 'value'
},

BAD Reuqest Cannot create and populate list type Microsoft.AspNetCore.Http.IFormFileCollection

I am receiving Bad request when uploading my file and converting it into json and passing to my .net core webapi controller.
here its an error screenshot.i have also console the model as well.
here its my code in typescript
const httpHeaders = new HttpHeaders({
'Content-Type': 'application/json',
});
var approval = {
...this.MemberApproval,
};
console.log(JSON.stringify(approval));
return this.http.post(this.Url + '/Member/UpdateMember/update', JSON.stringify(approval), { headers: httpHeaders });
on .net core webapi i am doing like this.
My model :
public class MemberApproval
{
public string Notes;
public IFormCollection Attachment;
public int ApprovalStatus;
public int SubsId;
public int MemberId;
}
My controller :
[Route("[action]/{item}")]
[HttpPost]
public IActionResult UpdateMember([FromBody]MemberApproval approval )
{
if (approval !=null)
{
_repo.UpdateMemberStatus(approval);
}
return Ok();
}
If you want to submit a file to ASP.Net Core you have to use FromForm and IFormFile like this
[HttpPost("SavePost")]
public async Task<IActionResult> SavePost([FromForm]PostViewModel viewModel)
{
var postOptionsViewModel = _jsonParsePostOptionDefaultVm.ToObject(viewModel.PostOptionsViewModel);
viewModel.PostOptionsDefaultViewModel = postOptionsViewModel;
if (viewModel.Id.HasValue)
{
await _postRepository.EditPost(viewModel);
}
else
{
await _postRepository.SavePost(viewModel);
}
return Ok();
}
My model will have property List so you can submit multi file to server
public List<IFormFile> File { get; set; }
My FE side code will be like this. I'm using react but mostly not different in the way we submit a formdata to server
const formdata = new FormData();
formdata.append("Title", this.state.title);
formdata.append("File", this.state.File);
Remember to set Content-Type header to 'multipart/form-data'

jQuery.get from Spring RestController

How can should I send the data from Spring controller to the client? Do I need to wrap it as Json or is there an easier way?
(noob in web. So, please bear with me)
#RequestMapping("/abc")
#RestController
public class ListController {
#RequestMapping(value = "/d", method = RequestMethod.GET)
public StringOrJson? getData() {
return "myData";
}
On the client:
function checkBoxToggled(){
$(document).get('abc/d', function( data ) {
alert('Data Loaded2:' + data );
});
}
It will be great if you declare the #RequestMapping as follows:
#RequestMapping(value = "/d", method = RequestMethod.GET, produces = "application/json")
You can return simple String response.
Or you can always reutrn JSONObject as follows:
return new JSONObject("{'data':'myData'}");
In that case the return value in the method signature should be replaced to JSONObject.
You just need to modify your Controller to:
#RequestMapping("/abc")
#Controller
public class ListController {
#RequestMapping(value = "/d", method = RequestMethod.GET)
public String getData() {
return "myData";
}
}
And the client should be:
jQuery.get("abc/d", function (data) {
alert('Data Loaded2:' + data );
});

Pass Array of Objects in http Post

I have a web api developed. I need to pass an array of objects
[{"Id":"10010","lati":"12.991845763535506","longi":"77.54596710205078","PSID":"1001"},
{"Id":"10011","lati":"12.97846402705198","longi":"77.55729675292969","PSID":"1001"},
{"Id":"10012","lati":"12.967758119178907","longi":"77.54425048828125","PSID":"1001"}]
The model class of web api is given below
Locate.cs
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
namespace webapi.Models
{
public class Locate
{
[Key][Required]
public string Id { get; set; }
public string lati { get; set; }
public string longi { get; set; }
public string PSID { get; set; }
}
}
and the code corresponding to post method in controller file is given below
LocatesController.cs
// POST: api/Locates
[ResponseType(typeof(Locate))]
public async Task<IHttpActionResult> PostLocate(Locate locate)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.Locates.Add(locate);
try
{
await db.SaveChangesAsync();
}
catch (DbUpdateException)
{
if (LocateExists(locate.Id))
{
return Conflict();
}
else
{
throw;
}
}
return CreatedAtRoute("DefaultApi", new { id = locate.Id }, locate);
}
private bool LocateExists(string id)
{
return db.Locates.Count(e => e.Id == id) > 0;
}
I send the http post request in my js script given below
app.js
$scope.adding = function()
{
var idd = $rootScope.vaar;
var datas = [];
var len = latitudes.length;
for (var i = 0; i < len; i++) {
datas.push({
"Id": idd + i.toString(),
"lati": latitudes[i].toString(),
"longi": longitudes[i].toString(),
"PSID": idd
});
}
var jsonData = angular.Json(datas);
var objectToSerialize = {'object':jsonData};
var data = $.param(objectToSerialize);
var config = {
headers: {
'Content-Type': 'application/-www-form-urlencoded;charset=utf-8'
}
}
$http.post('http://localhost:8080/pool/api/locates/', data,config).success(function (data, status, headers, config) {
alert("Success");
}).error(function (data, status, header, config) {
alert("An error has occured while adding!"+status);
});
}
It does not add the above array. Please help me
the problem is here:
[ResponseType(typeof(Locate))]
public async Task<IHttpActionResult> PostLocate(Locate locate)
and you are posting an array so it should be:
[ResponseType(typeof(Locate))]
public async Task<IHttpActionResult> PostLocate(List<Locate> locates)
The problem is solved. I changed the parameter to (List<Locate> locates) and made a logic inside post method. Thank you Glenn Packer

Office Apps, how send copy of doc file with ajax to C# controller

hello i have this problem:
I have a addins for office(word);
I want to send a copy of current file (.docx) to C# controller, i have this code now, at this stage of the code i get a array of chars or somethis in the "yourfile", how ca i get a .docx file?
JavaScript
function sendFile() {
Office.context.document.getFileAsync("compressed",
{ sliceSize: 100000 },
function (result) {
if (result.status == Office.AsyncResultStatus.Succeeded) {
var myFile = result.value;
var state = {
file: myFile,
counter: 0,
sliceCount: myFile.sliceCount
};
getSlice(state);
}
});
}
function getSlice(state) {
state.file.getSliceAsync(state.counter, function (result) {
if (result.status == Office.AsyncResultStatus.Succeeded) {
sendSlice(result.value, state);
}
});
}
function myEncodeBase64(str)
{
return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) {
return String.fromCharCode('0x' + p1);
}));
}
function sendSlice(slice, state) {
var data = slice.data;
if (data) {
var fileData = myEncodeBase64(data);
var _url = '../../api/file';
useAjax(_url, 'Post', JSON.stringify(fileData), _contentType).done(function (data) {
writeData(data);
app.showNotification("Translation was successfully done!");
});
}
}
And the C# CONTROLLER:
public static string filemame = #"c:\yourfile";
[Route("file")]
[HttpPost]
public void getFile([FromBody] string data)
{
Base64ToFile(data,filemame);
}
public static void Base64ToFile(string base64String, string filename)
{
byte[] fileByteArray = Convert.FromBase64String(base64String);
// Instantiate FileStream to create a new file
System.IO.FileStream writeFileStream = new System.IO.FileStream(filename, System.IO.FileMode.Create, System.IO.FileAccess.Write);
// Write converted base64String to newly created file
writeFileStream.Write(fileByteArray, 0, fileByteArray.Length);
// Clean up / disposal
writeFileStream.Close();
}
Late to the party, but I'm adding the answer here nonetheless, in case someone else will need it at some later date.
Instead of using myEncodeBase64 you should use
var fileData = OSF.OUtil.encodeBase64(data);
It's a function that is part of the Office API, so you don't have to define anything else.
I have been struggling to construct a correct pptx serverside. Eventually this is what I came up with.
Javascript
function sendSlice(slice, state) {
var data = slice.data;
if (data) {
var isLastSlice = state.counter >= (state.sliceCount -1);
var ajaxData = {
isLastSlice: isLastSlice,
counter: state.counter,
documentData: btoa(data)
}
$.ajax({
url: "/api/Constructpptx", method: "POST", data: ajaxData, success: function (result) {
state.counter++;
if (isLastSlice) {
closeFile(state);
}
else {
getSlice(state);
}
}, error: function (xhr, status, error) {
}
});
}
}
And as an API backend I use this
C# ApiController
public class ConstructpptxController : ApiController
{
public static List<byte> Document { get; set; } = new List<byte>();
public string Post([FromBody]ConstructpptxPayload payload)
{
if (payload.counter == 0)
Document.Clear();
var payloadData = Convert.FromBase64String(payload.documentData);
var pptBytes = Encoding.UTF8.GetString(payloadData).Split(',').Select(byte.Parse).ToArray();
Document.AddRange(pptBytes);
if(payload.isLastSlice)
{
var path = #"C:/Some/Local/Path/Presentation.pptx";
var fileStream = new FileStream(path, FileMode.Create, FileAccess.ReadWrite);
fileStream.Write(Document.ToArray(), 0, Document.Count());
fileStream.Close();
Document.Clear();
}
return $"Counter: {payload.counter}, isLast: {payload.isLastSlice}, docLength: {Document.Count}";
}
}
public class ConstructpptxPayload
{
public bool isLastSlice { get; set; }
public int counter { get; set; }
public string documentData { get; set; }
}
Please note: only use this example as a quick starting point, as you don't want to save the bytes in a static List Document. Instead you want to make your webserver stateless.

Categories