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 );
});
Related
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.
I want to pass configuration values from appsettings.json in ASP.Net Core / 5.0 to a client-side plain JavaScript code; the parameters will not be changed after setup. What is the easiest way to do it?
You can:
1 - expose a controller action to fetch configuration and call the backend from JS.
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
private readonly IConfiguration _config;
public ValuesController(IConfiguration config)
{
_config = config;
}
[HttpGet("config")]
public ActionResult Get()
{
var data = new
{
SomeValue = _config["SomeValue"]
};
return Ok(data);
}
}
fetch('api/values/config').then(function(response) {
console.log(response);
})
2 - write the vales directly to the HTML page.
public class HomeController : Controller
{
private readonly IConfiguration _config;
public HomeController(IConfiguration config)
{
_config = config;
}
public IActionResult Index()
{
var model = new HomeIndexModel
{
SomeValue = _config["SomeValue"]
};
return View(model);
}
}
Index.cshtml
#model MyApp.Controllers.HomeIndexModel;
<script type="text/javascript">
window['portalData'] = #Json.Serialize(Model);
</script>
<app-root></app-root>
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'
},
I am facing an issue while retrieving data from client to controller.
I got 400 Bad Request error and I cannot find the reason for it.
I am using dojo gridx here and this is the js file
function goToReviewTargetsPage(){
var gridSelectedData = JSON.stringify( dijit.byId("geneGridNodeforSelectTargets").store.data);
dojo.xhrPost({
url : contextPath + '/updateGeneData.htm',
handleAs: 'json',
headers: {
'Content-Type': 'application/json',
},
applyAroundAdviceOnLoad : true,
preventCache : true,
content :
{
"selectedTargetsData" : gridSelectedData
},
load : function(data)
{
\\do something
},
error : function(error)
{
hideLoadingDialog();
}
});
}
The json data in gridSelectedData mentioned in above js is:
[{"id":1,"name":"ABL1","diseases":[{"id":1,"diseaseName":"CANCER"}],"SV":true,"CNV":true,"SNP":true},{"id":2,"name":"ALK","diseases":[{"id":1,"diseaseName":"CANCER"}],"SV":false,"CNV":true,"SNP":true},{"id":3,"name":"BLA","diseases":[{"id":1,"diseaseName":"CANCER"}],"SV":false,"CNV":false,"SNP":true},{"id":4,"name":"ALS","diseases":[{"id":2,"diseaseName":"LUNGS"}],"SV":false,"CNV":true,"SNP":true}]
This is the code from the controller
#RequestMapping(value = "/updateGeneData", produces = MediaType.APPLICATION_JSON_VALUE,
consumes = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.POST)
#ResponseBody
public List<Gene> getSelectedGenes(#RequestBody Gene[] genes,
HttpServletResponse response, HttpServletRequest request)
{
List<Gene> geneList = new ArrayList<>();
// do something
return geneList;
}
Gene.java (POJO)
public class Gene {
private Integer id;
private String name;
private boolean SNP = false;
private boolean SV = false;
private boolean CNV = false;
Set<Disease> diseases = new HashSet<Disease>();
//getters and setters
}
This is the Request Header
Accept:*/*
Accept-Encoding:gzip, deflate
Accept-Language:en-US,en;q=0.9
ajaxRequest:true
Connection:keep-alive
Content-Encoding:UTF-8
Content-Length:795
Content-Type:application/json
X-Requested-With:XMLHttpRequest
The payload is:
[{id: 1, name: "ABL1", diseases: [{id: 1, diseaseName: "CANCER"}], SV: true, CNV: true, SNP: true},…]
change the post request from /updateGeneData.htm on /updateGeneData and delete attributes produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE,
Your controller is wanting an array [] and you're passing it a list. Your controller should be
#RequestMapping(value = "/updateGeneData",
produces MediaType.APPLICATION_JSON_VALUE,
consumes = MediaType.APPLICATION_JSON_VALUE,
method = RequestMethod.POST)
#ResponseBody
public List<Gene> getSelectedGenes(#RequestBody List<Gene> genes) {
List<Gene> geneList = new ArrayList<>();
// do something
return geneList;
}
I have found that sometimes I need to wrap my DTO in order for Jackson to work. This approach as worked for me in the past.
class Genes extends ArrayList<Gene> { }
#ResponseBody
public List<Gene> getSelectedGenes(#RequestBody Genes genes) {
How can I call a generic WebAPI action from JavaScript? and pass the T type.
C#:
public class ClassUtilitiesController : ApiController
{
[HttpPost]
public string GetClassNamespace<T>()
{
return typeof(T).FullName;
}
}
JavaScript:
$.post('/api/ClassUtilities', {
T: 'string',
// ...
});
I need an action that returns something from input T type (ex. typeof(T).FullName or Create an instance and call a method). What should I do?
The JSON data of the POST request it's actually a string, meaning that you have to deserialize is as the object you want.
Try:
public class ClassUtilitiesController : ApiController
{
[HttpPost]
public string GetClassNamespace(string data)
{
T t;
try
{
t = JsonConvert.DeserializeObject<T>(data);
}
catch (Exception e)
{
return e;
}
return t.FullName;
}
}