BE AJAX request delivers empty repository - typo3

I want to build an BE extension that is reading the repository from another extension and delivers the data as CSV/XSL/XSLX without saving it on the server. e.g Outputs the data in a blank window with modified headers.
The BE AJAX request is fired properly with
$TYPO3_CONF_VARS['BE']['AJAX']['tx_myext::ajaxID'] = 'filename:object->method';
The repository if called from the backend does work fine too.
public function ajaxAction() {
...
$this->extRepository =& t3lib_div::makeInstance('Tx_MySecondExt_Domain_Repository_DataRepository');
...
}
but when called from domain.tld/typo3/ajax.php?ajaxID=tx_myext::ajaxID
it doesnt find Tx_MySecondExt_Domain_Repository_DataRepository also if i call the repository of the second repository with the findAll() methode directly by AJAX. It does only return NULL.
also when setting the QuerySettings by hand
public function findAllexport() {
$query = $this->createQuery();
$query->getQuerySettings()->setRespectStoragePage(FALSE);
return $query->execute();
}
Also FYI its on 4.5
Edit:
Calling the repository with the ObjectManager doesn't work too
$objectManager = t3lib_div::makeInstance('Tx_Extbase_Object_ObjectManager');
$this->extRepository = $objectManager->get('Tx_MySecondExt_Domain_Repository_DataRepository');

Did you make sure that the other extension is loaded before your own extension is loaded? Look at your localconf.php. Normally you need to specify the dependencies in your ext_emconf.php before you install your extension.
Also make sure that you have added both extension's configurations to the Static Includes of your TypoScript template.

inside the export action
... Repository to file generation
header('Content-Type: application/vnd.ms-excel');
header('Content-Disposition: attachment;filename="data.xls"');
header('Cache-Control: max-age=0');
// If you're serving to IE 9, then the following may be needed
header('Cache-Control: max-age=1');
// If you're serving to IE over SSL, then the following may be needed
header ('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); // Date in the past
header ('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT'); // always modified
header ('Cache-Control: cache, must-revalidate'); // HTTP/1.1
header ('Pragma: public'); // HTTP/1.0
... output file
exit;
done, no ajax plus pretty simple and stupid ;)
still if somone knows a awnser to the intial probelem i would appreciate it.

Related

Empty MultipartFile[] when sending files from Vue to SpringBoot controller

I'm doing a program that will help me to make monthly reports and I stuck at uploading photos which I need for one kind of the reports. For some reason, it doesn't get an array in the controller.
I use Springboot RestController at the backend and Vue with BootstrapVue and vue-resource on the other side.
index.html (BootstrapVue):
<b-form-file
v-model="photos"
accept="image/*"
multiple
placeholder="..."
></b-form-file>
<b-button #click="uploadPhotos">Upload</b-button>
inside vuemain.js:
data: {
photos: null,
},
methods: {
uploadPhotos(){
var formData = new FormData();
formData.append("photos", this.photos);
this.$http.post('reports/photo', formData).then(result => {
...
})
}, ...
inside Controller:
#PostMapping("/photo")
public void addPhoto(#RequestParam("photos") MultipartFile[] photo) {
System.out.println(photo.length); // shows 0
}
what I see inside Params at browser:
XHRPOSThttp://localhost:8080/reports-maker/reports/photo
[HTTP/1.1 500 326ms]
Request payload
-----------------------------4469196632041005505545240657
Content-Disposition: form-data; name="photos"
[object File],[object File],[object File],[object File]
-----------------------------4469196632041005505545240657--
​
So for some reason at this point #RequestParam("photos") MultipartFile[] photo it's empty array. But if I change it to just one photo like this: #RequestParam("photos") MultipartFile photo and send one from js: formData.append("photos", this.photos[0]); everything works nicely and photo gets uploaded to the server.
It's my first experience with Vue and to be honest I don't want to go deep into JS learning, so probably there is some silly mistake somewhere. Any way I can use a loop in JS method to upload them one by one, but that would be so ugly. I hope there is a better way to do it (without any additional JS libraries of course).
If you use axios then you should add header
var headers = {
'Content-Type': 'multipart/form-data',
};
axios.post(
'reports/photo',
formData,
{
headers: headers,
}
)
...
to be able send files to the server.
I agree, sending files in separate requests one by one is very "ugly", but I also don't like the idea of not using the mapping resources of Spring Boot, having to send all files with different names (seems disorganized) and having to work with MultipartHttpServletRequest, but there is a simple solution for this: Ian's answer to this question (not realy related to Vue.js, but useful) worked for me:
In order for Spring to map items in a request to a list, you need to provide the same name (in the FormData.append calls) for each item when appending to the form data. This allows Spring to effectively see the request as name=value1&name=value2&name=value3 (but obviously in the form of form data). When Spring sees the same key ("name") multiple times, it can map the values into a collection.
In your .vue file, append the photos with the same name:
for (let i = 0; i < this.photos.length; i++) {
formData.append("photos", this.photos[i]);
}
And in your Controller:
#PostMapping("/photo")
public void addPhoto(#RequestParam("photos") MultipartFile[] photo) {
System.out.println(photo.length); // Should be greater than 0 now
}
Note:
I used Vue Axios to consume my API and manually added the Content-Type: multipart/form-data header. Make sure its in your request header list.
I found an acceptable solution here https://stackoverflow.com/a/33921749/11508625 Rossi Robinsion's code works nicely. At least it looks better than sending files in separate requests one by one.
The answer is based on using getFileNames() which helps to iterate on files inside a request even if they are not in the array.

Response is giving // slashes at start - Taffy - ColdFusion

I have setup my first REST API and I am new to using the Taffy framework.
I have a site which is working on ColdFusion 10, IIS and using ColdBox. I have setup a hello world example in a directory. I am getting // two slashes in the response. Here is an example of the response:
//["hello","world"]
My hello.cfc looks like this:
component extends="taffy.core.resource" taffy_uri="/hello" {
function get(){
return representationOf(['hello','world']);
}
}
My application.cfc looks like this:
<cfcomponent extends="taffy.core.api">
<cfscript>
this.name = hash(getCurrentTemplatePath());
this.mappings["/resources"] = listDeleteAt(cgi.script_name, listLen(cgi.script_name, "/"), "/") & "/resources";
variables.framework = {};
variables.framework.reloadKey = "reload";
variables.framework.reloadPassword = "test";
variables.framework.serializer = "taffy.core.nativeJsonSerializer";
variables.framework.returnExceptionsAsJson = true;
function onApplicationStart(){
return super.onApplicationStart();
}
function onRequestStart(TARGETPATH){
// reload app to make any envoirnmental changes
if(structkeyexists(url,'reloadApp')){
applicationStop();
location('index.cfm');
}
// load Taffy onRequestStart before our stuff
super.onRequestStart();
if (request.taffyReloaded) {
// reload ORM as well
ORMReload();
}
}
function onTaffyRequest(verb, cfc, requestArguments, mimeExt){
return true;
}
function onError(Exception)
{
writeDump(Exception);
abort;
}
</cfscript>
</cfcomponent>
Can anyone tell me where I am going wrong?
Does this have something to do with using ColdBox?
That is coming from a server side setting in the ColdFusion admin, under settings. Prefix serialized JSON with. Beginning with ColdFusion 10 it is enabled by default for security. (I believe the feature was added with ColdFusion 9.) Protects web services, which return JSON data from cross-site scripting attacks by prefixing serialized JSON strings with a custom prefix. You could turn it off there but I do not recommend that. Instead you should handle it with your code.
See this post from Raymond Camden - Handling JSON with prefixes in jQuery and jQueryUI
NOTE: this setting can also be set per-application by setting secureJSON and secureJSONPrefix in your Application.cfc file. See the documentation about that here - Application variables.
secureJSON - A Boolean value that specifies whether to add a security prefix in front of the value that a ColdFusion function returns in JSON-format in response to a remote call.
The default value is the value of the Prefix serialized JSON setting in the Administrator Server Settings > Settings page (which defaults to false). You can override this value in the cffunction tag.
secureJSONPrefix - The security prefix to put in front of the value that a ColdFusion function returns in JSON-format in response to a remote call if the secureJSON setting is true.
The default value is the value of the Prefix serialized JSON setting in the Administrator Server Settings > Settings page (which defaults to //, the JavaScript comment character).

Custom XML response in sails.js blueprint for a model?

I am new to sails.js and I have a simple blueprint model set up. Right now, my controller and model are pretty much empty except for attribute definitions on the model.
After the model is created via POST, I would like the response to be a custom XML response (some plain text I generate essentially), not the standard JSON response. I figured that I could overwrite the entire create method on the controller, essentially copy-and-pasting the code from the default and just overwriting the response, but that seems really heavy too me.
There must be a better way to do this?
Note that I am only attempting to do this for this specific model, not generally.
Thanks!
The best way is to simply add the header as DigitalDesignDj mentioned.
/**
* TestController
*/
module.exports = {
create: function(res, req) {
// get your data
var xml = 'some xml string';
res.setHeader( "Content-type", "text/xml" );
res.send(xml);
}
}
To change headers for a specific response.
response.setHeader( "Content-type", "text/xml" );
When you already have some XML for the response.send()
If your result was to do this for all actions on that single model you could simply overwrite the toJSON method to generate XML instead of JSON in the model itself. Then if your running blueprints, it will spit out XML instead of json when you hit those endpoints.
However your question is specific to the create action. In this instance, I would ask if your running alternate view files for non ajax requests. And if not, just drop an view files into the create action that views/foo/create.[ejs,jade,ect...] with your xml layout. The response will see the view file and override the json output with that file. This means you have to change no code just add that single file.
Their are a dozen ways to accomplish this, and your question would need more detail (as mentioned on the comments) for a specific answer to your use case.

WWW::Mechanize - how to POST without affecting page stack and/or current HTML::Form object?

I'm using WWW::Mechanize to automate placing 'orders' in our supplier's portal (with permission). It's pretty straight-forward to do so by filling the relevant form fields and submiting as normal.
However, the portal has been built with a JavaScript-capable client in mind, and some short-cuts were taken as a result; the most significant short-cut they took is that as you progress through a "wizard" (series of forms) with normal POSTS, they require that you "deallocate" some resources server side for the "previous wizard step" by doing an AJAX POST. In pseudo-code:
GET page #1
fill the fields of page #1
POST (submit the form) --> redirects to page #2.
POST (ajax request to "/delete.do")
fill the fields of page #2
POST (submit the form) --> redirects to page #3.
POST (ajax request to "/delete.do")
fill the fields of page #3.
...
What's the easiest approach to do those ajax request to "/delete.do" requests?
I've tried...
Appoach (A)
If I inject a new form (referencing /delete.do in the action) into the DOM and use submit then the mech object will no longer have the HTML::Form object built from the previous redirects to page #X step.
If I just use back() from that point, does that make another GET to the server? (or is it just using the prior values from the page stack?)
Approach (B)
If I just use the post() method inherited from LWP::UserAgent to send the POST to /delete.do I get a security error -- I guess it's not using the cookie jar that has been set up by WWW::Mechanize.
Is there some canonical way to make an 'out-of-band' POST that:
Does use/update WWW::Mechanize's cookie jar
Does follow redirects
Doesn't alter the page stack
Doesn't alter the current HTML::Form object
UDPATE:
For anyone trying to replicate the solution suggested by gangabass, you actually need to:
(1) Subclass WWW::Mechanize, overriding update_html such that a
new content can be injected into the HTML on demand.
This content would normally be parsed by HTML::Form::parse(). The
override sub needs to alter the first non-self parameter $html
before calling the original implementation and returning the result.
package WWW::Mechanize::Debug;
use base 'WWW::Mechanize';
sub update_html {
my ($self,$html) = #_;
$html = $WWW::Mechanize::Debug::html_updater->($html)
if defined($WWW::Mechanize::Debug::html_updater);
return $self->SUPER::update_html($html);
}
1;
(2) In the main program, use WWW::Mechanize::Debug as per
WWW::Mechanize
use WWW::Mechanize::Debug;
my $mech = WWW::Mechanize::Debug->new;
(3) Inject the HTML form which will need to be submit()ed.
{
my $formHTML = qq|
<form action="/delete.do" method="POST" name="myform">
<!-- some relevant hidden inputs go here in the real solution -->
</form>
|;
local $WWW::Mechanize::html_updater = sub {
my ($html) = #_;
$html =~ s|</body>|$formHTML</body>|;
};
# Load the page containing the normal wizard step content.
$mech->get($the_url);
# This should how have an extra form injected into it.
}
(4) In a new scope clone() the mechanize object, fill the form and
submit it!
{
my $other = $mech->clone;
my $myform = $separate->form_name('my_form');
$myform->field('foo' => 'bar'); # fill in the relevant fields to be posted
$myform->submit;
}
(5) Continue using the original mechanize object as if that form
submission had never occurred.
You need to clone your Mech object and make POST from cloned version. Something like:
{
my $mech = $mech->clone();
$mech->post(....);
}
But of course it will be better to make sub for this.

POST to ASP.NET WebAPI using Fiddler2

I have a class that models exactly the entity I have in the database. I have a stored procedure that takes in parameters for a new row and returns all the settings in the table which in turn populates my repository. I am able to see the results of GET, PUT and DELETE in the List of type Setting that is in memory. I am noticing first that even when I close Visual Studio and reopen and run the project, sometimes, the List is still in the state it was before. It is not repopulating from the database so I'm not sure why that is first of all... Secondly, I can't seem to get POST to work from Fiddler unlike the other HTTP verbs. I DO see the values from Fiddler show up in the code below but I get the error: Invalid URI: The format of the URI could not be determined. I get the same error if I pass an ID or not.
Here is what I put into Fiddler:
POST localhost:54852/api/settings
Request Headers
User-Agent: Fiddler
Content-type: application/x-www-form-urlencoded
Host: localhost:54852
Content-Length: 149
Request Body
ID=0&Category=Dried%20Goods&Sub_Category=Other&UnitSize=99&UnitOfMeasureID=999&Facings=true&Quantity=true&EverydayPrice=999.99&PromotionPrice=111.11
PostSetting function within my SettingsController
public HttpResponseMessage PostSetting(Setting item)
{
item = repository.Add(item);
var response = new HttpResponseMessage<Setting>(item) { StatusCode = HttpStatusCode.Created };
string uri = Url.Route("DefaultApi", new { id = item.ID });
response.Headers.Location = new Uri(uri);
return response;
}
Should I create a new procedure that gets the MAXID from the database and use that as the NEW ID in the line above where a new ID is created?
You need to create a JSON representation of the Setting class or item that you are wanting to test with use Fiddler (now a Telerik product) and use the Composer tab.
Next you will want to perform a POST to the following URL:
http://[your base url]/api/settings
and pass the JSON formatted setting class.
You can see an example of this here: ASP.NET Web API - Scott Hanselman
Here is a short video showing how to achieve it easily
get and post to webapi from fiddler