I feel like I must be missing something obvious because the REST documentation seems so simple and the code I produced appears to work correctly unless I try to access it via REST.
hello.cfc:
component rest="true" restpath="restTest"{
remote string function sayHello() httpMethod="get"{
return "Hello World";
}
}
Service Mapping:
I have tried both default yes and no with no change.
Test Page:
<html>
<head>
<title>REST Test</title>
</head>
<body>
Calling service as an object:<br>
<cfset restTest = new hello() />
<cfdump var="#restTest.sayHello()#" />
<br>
Calling service via http:<br>
<cfhttp url="http://localhost/rest/restTest" result="restResult" method="GET" />
<cfdump var="#restResult#" />
</body>
</html>
Results:
Did you try accessing without directing the call through a connector/webserver?
Keep your project inside /cfusion/wwwroot/ and then try accessing it via browser
http://localhost:8500/rest/restTest
Sample test also worked for me after changing the URL
enter image description here
It seems like you are using a wrong URL when making HTTP request to the REST service. The URL should be like this:
http://{domain}/rest/{service mapping name}/{component level rest path}/{function level restpath}
So in your case the correct URL should be:
http://localhost/rest/api/restTest
For more info read this http://www.adobe.com/devnet/coldfusion/articles/restful-web-services.html
Related
I've built a RESTful service with Spring (java annotation based configuration) which I can execute successfully via Curl. I'm trying to submit files via a HTML Form too, however that's not working.
#RequestMapping(path = "/upload", method = RequestMethod.POST)
public String handleFileUpload(#RequestPart(value = "file") MultipartFile file,
RedirectAttributes redirectAttributes) {
logger.info("POST '/upload'");
storageService.store(file);
redirectAttributes.addFlashAttribute("message",
"You successfully uploaded " + file.getOriginalFilename() + "!");
return "redirect:/";
}
And I'm submitting a file via Curl as follows:
curl -i -H "Content-Type: multipart/*; boundary=------------BOUNDARY--" -X POST --noproxy localhost, localhost:8080/upload -F "file=#test.txt"
Even though my form submission has an input of type file, with the name file, I get this error via a HTML form
org.springframework.web.multipart.support.MissingServletRequestPartException: Required request part 'file' is not present
From what I've been investigating, it would seem as if the controller would expect a Model Attribute when the file is submitted via HTML Form, so what could be a good practice to resolve this? Include a controller parameter for a Model Attribute, which would be checked for null value (to distinguish between html form or other submission methods), or would a sort of Proxy controller between the HTML Form and the RESTful service be better?
The service looks good. It works fine for me on both CURL and HTML form submit.
Here is my form. Please try using this.
<html>
<head>
<title>Post Tool</title>
</head>
<body>
<h1>Sample Requests</h1>
<h2>Upload Document</h2>
<form action="http://localhost:8080/upload" method="post" enctype="multipart/form-data">
Choose a file : <input type="file" name="file" multiple/>
<input type="submit" value="Upload" />
</form>
</body>
</html>
After more research I got to know that the commons multi part resolver doesn't fare well with the new versions of spring boot. It struggles obtaining POST parameters from forms.
One solution is to use the StandardServletMultipartResolver implementation of the MultipartResolver interface!
I'm trying to add a single, simple client-only validation rule while using jQuery unobtrusive. My validation function is never called, the alert never fires. What am I doing wrong? I've stripped this down from a much more complex MVC application.
<html>
<head>
<script src="//ajax.aspnetcdn.com/ajax/jQuery/jquery-2.1.3.min.js"></script>
<script src="//ajax.aspnetcdn.com/ajax/jquery.validate/1.13.1/jquery.validate.js"></script>
<script src="//ajax.aspnetcdn.com/ajax/mvc/5.2.3/jquery.validate.unobtrusive.js"></script>
<script>
jQuery.validator.addMethod("mysplit", function () {
alert("in validator");
return false;
}, "Barf");
result = jQuery.validator.unobtrusive.adapters.addBool("mysplit");
</script>
</head>
<body>
<form method="post">
<input type="text" data-val="True", data-val-mysplit="error msg" />
<input type="submit" />
</form>
</body>
</html>
Not sure if this matters for a simple .htm file but in my web.config, everything looks correct:
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
<add key="ValidationSettings:UnobtrusiveValidationMode" value="none" />
I am still unable to decorate an HTML element to make it work with unobtrusive validation. It appears that if you don't have an adaptor for your custom rule, then manually adding the unobtrusive HTML attributes will not work. However I did discover that you can decorate elements to be validated directly by jQuery.validate (more or less skipping the unobtrusive validation). I don't know if manually adding jQuery.validation data attributes this way will conflict with the validation done by unobtrusive if you have, for example, a [Required] attribute on the element that gets converted to the "data-val" attributes by unobtrusive.
In short you can add a client validation method with the usual jQuery.validator.addMethod() then trigger it with the proper data-rule attributes (not data-val, which unobtrusive uses). For example to validate that an input field has the value "hello", I can add a rule:
jQuery.validator.addMethod("hello", function (value, element, params) {
return this.optional(element) || /^hello$/.test(value);
});
Note: don't add the error message param to addMethod, it will conflict with #Html.ValidationMessageFor() if you are using that.
Then manually decorate your HTML element like:
#Html.EditorFor(model => model.sendOn, new
{
htmlAttributes = new
{
data_rule_hello="true"
}
})
Any jQuery.validate will fire.
Note that trying to use data-rule-pattern="hello" just refused to work for me so I went the addMethod() route.
In my case rather that switch totally away from unobtrusive just because I can't validate this one input is a much worse option than this bit of a hack to do my custom validation of an input element or two here or there.
This article was key to exposing the data-rule magic.
I have yet to find out if this technique causes any serious problems in production but it seems to work for me.
I would also recommend that people consider writing a custom adaptor for their own model attributes if they need custom validation instead of a one-off hack like this.
I am currently creating an engine for a client to submit XML to our web site, and I would like to process the data to a CFC. In order to test this, I have set up a simple form in a regular CFM file, as such...
<!DOCTYPE html>
<html>
<head>
<title>Testing CFC processing</title>
</head>
<body>
<cfsavecontent variable="variables.testxml">
<?xml version="1.0" encoding="UTF-8"?>
<xmlRequest><headers>data</headers><body><Notification><Result Success="1"/><participantID>[ID number]</participantID><transactionNumber>000</transactionNumber></Notification></body></xmlRequest>
</cfsavecontent>
<form method="post" action="[site url]/main.cfc?method=testData">
<cfoutput>
<textarea name="data" cols="150" rows="5">#variables.testxml#</textarea>
</cfoutput>
<br/>
<input type="submit" name="submit" value="Process Test" />
</form>
</body>
</html>
In the main.cfc I have a method called testData which is set up as follows...
remote void function testData(data) {
writeOutput(arguments.data);
}
This test is just to check to see if the method is receiving the data it is sent. When I run it, it does not error, but it also does not output the XML data from the form.
In case it is pertinent, I have the component declared as follows...
component displayname="[name]" accessors="true" output="true"
I can't figure out why the CFC is not receiving the form data (or if it is, why it is not outputting the form data). Can anyone offer any assistance?
I found the answer. It turns out there is no problem with the code above. The problem was in the Application.cfc. I had a method onCFCRequest that didn't have any code in it. It was blocking the CFC from receiving the data. After removing the function from my Application.cfc the method was able to receive the data without issue.
I am trying to create a simple interface, that will use XForms to display a button that say "Drop a Database". I then want to be able to invoke a RestXQ document called dropdatabase.xqm which is called when the button on the form is clicked. I am using BaseX. I saved my XForm in a file called onlydel.xml in the basex/webapp/static folder. I created my RestXQ program called dropdatabase.xqm and saved it to my basex/webapp folder. I have created a database called patients.
xforms: The contents of onlydel.xml is:
<?xml-stylesheet href="xsltforms/xsltforms.xsl" type="text/xsl"?>
<?xsltforms-options debug="yes"?>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:xf="http://www.w3.org/2002/xforms"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<head>
<title>XFORMS IN XHTML</title>
<model xmlns="http://www.w3.org/2002/xforms" id="order-model">
<instance>
<soap xmlns="">
</soap>
</instance>
<submission action="/dropdatabase" method="post" id="s06"/>
</model>
</head>
<body>
<h2>DATABASE</h2>
<div style="float:center;">
<fieldset style="width:50%">
<xf:submit submission="s06"><xf:label>Drop A Database</xf:label></xf:submit>
</fieldset></div>
</body>
</html>
RestXQ :The contents of dropdatabase.xqm is:
module namespace _ = 'http://exquery.org/ns/restxq';
(:~
: Deletes the blog database and redirects the user to the main page.
:)
declare
%restxq:path("/dropdatabase")
%restxq:GET
function _:dropdatabase()
{
(db:drop("patients"))
};
When I run this I get the following error:
Stopped at /home/ubuntu/basex/webapp/dropdatabase.xqm, 10/13:
[XUST0001] StaticFunc expression: no updating expression allowed.
The help I need is:
Can I do something like this with the code I have written.
What is the reason for the error and a solution to eliminate the error too would be helpful
The error message seems quite clear to me: db:drop() is an updating expression and is hence not allowed at this point. You have to mark the function as an updating function by using the %updating annotation.
I've recently started experimenting with AngularJS. I am building a simple html5 application that updates a MySQL database.
[index.html]
<!DOCTYPE html>
<html ng-app="MyProject">
<head>
<title>My Project</title>
<link rel="stylesheet" href="css/main.css" type="text/css">
<script src="lib/angular-1.0.1.js"></script>
<script src="lib/angular-resource-1.0.1.js"></script>
<script src="js/controllers.js"></script>
<script src="js/services.js"></script>
</head>
<body>
<div id="main-content" ng-view>
</body>
</html>
I used the Slim framework to create a Rest Interface. My database has currently one table named location_types with two columns id and title. I have tested the Rest service in the browser so under api/locationtypes I get the following JSON:
[{"id":"1","title":"Airport"},{"id":"2","title":"Bus Station"}]
I create the service in AngularJS using the following code:
[services.js]
angular.module('myDB', ['ngResource']).
factory('LocationTypes', function($resource) {
var LocationTypes = $resource('http://localhost/project/api/locationtypes', {}, { query: {method: 'GET', isArray: true}});
return LocationTypes;
});
I also use the following code to create the app module:
[controllers.js]
angular.module('MyProject', ['myDB']).
config(function($routeProvider) {
$routeProvider.
when('/locationtypes', {controller: LocationTypesCtrl, templateUrl:'forms/locationtypes.html'}).
otherwise({redirectTo:'/locationtypes'});
});
function LocationTypesCtrl($scope, LocationTypes)
{
$scope.locationTypes = LocationTypes.query();
}
The problem is that I get no results after querying the service. The locationTypes array is of zero length when I debug. I am using the latest AngularJS release [1.0.1]. What do I miss?
Is your URL really 'http://localhost/project/api/locationtypes' or is it an external server?
If its external, then you have a CORS (cross origin) issue. Unless I'm missing something it looks correct to me.
Probably a CORS issue like Dan said.
You can bypass this by adding the following to your module config.
.config(function($httpProvider){
delete $httpProvider.defaults.headers.common['X-Requested-With'];
})
Deleting the headers set by Angular should resolve the CORS issue.
You should also add a .htaccess file in your api folder. And add this:
Header set Access-Control-Allow-Origin "*"