Respond with both body and status code in Nancy - nancy

I'm new to Nancy and I want to return both a custom HttpStatusCode and a body (content). If I return an HttpStatusCode, it returns it with a blank body. If I return a string then it returns that as the body but always with a 200 status code of OK.
public class SendSMS : NancyModule
{
public SendSMS()
{
Post["/SendSMS"] = parameters =>
{
return HttpStatusCode.BadRequest; // this works, no body
return "Missing \"to\" parameter"; // this works, 200 status code
// want to return status code with message
};
}
}

You could always create an instance of the Response type and set the Body and StatusCode yourself. If you wanted to take a shortcut you could do something like
var r = (Response)"Some string that goes into the body";
r.StatusCode = 123;
return r;

This should work.
public class SendSMS : NancyModule
{
public SendSMS()
{
Post["/SendSMS"] = parameters =>
{
return Negotiate.WithModel("Missing \"to\" param")
.WithStatusCode(HttpStatusCode.BadRequest)
};
}
}
For more information check the docs on controlling content negotiation.

This is the simplest way I've found:
Return from your Module:
return new Response {
StatusCode = HttpStatusCode.NotFound, ReasonPhrase = "Resource not found"
};

If you have problems with encoding it's better to use
return new TextResponse(HttpStatusCode.STATUS, "Text Responsé")

Related

firebase function state pending and return undefined

I'm trying to make an input form that will check if the data exists in firebase database, below is the code that I used to check the data :
if(element.validation.codeunique) {
function checkCode(inputcode) {
firebaseUsers.orderByChild('code')
.equalTo(inputcode).once('value')
.then( snapshot => {
let thecode = null;
if(snapshot.val()){
thecode = false;
} else {
thecode = true;
}
console.log(thecode)
})
}
let checkcode = null;
checkcode = checkCode(element.value);
console.log(checkcode)
const valid = checkcode;
const message = `${!valid ? 'Code Exists':''}`;
error = !valid ? [valid,message] : error
}
in database i have a data :
users
-L3ZeHOI7XOmP9xhPkwX
-code:"DEM"
when I entered data DEM at the form :
console.log(thecode) result is false (which is the result that i want)
and when i entered another data ASD at the form :
console.log(thecode) result is true(which is the result that i want)
so the firebaseUsers actually is giving me the feedback/data that I want, but when I tried to get the data at valid with true/false,
this is the code that I originally used:
if(element.validation.codeunique) {
function checkCode(inputcode) {
firebaseUsers.orderByChild('code')
.equalTo(inputcode).once('value')
.then( snapshot => {
if(snapshot.val()){
return false;
} else {
return true;
}
})
}
const valid = checkCode(element.value);
const message = `${!valid ? 'Code Exists':''}`;
error = !valid ? [valid,message] : error
}
the valid shows = undefined,
my goal is to make the valid shows true/false,
could someone help me, and point out, what did i do wrong?
*I make the first code just to point out that the firebase is actually working
*the second code is the one that I originally used
There are a few issues that are standing out to me.
First, the code that you use originally was using return inside of the function's if / else conditional. I believe this is correct, you'll want to go back to doing that.
Second, the firebase.orderByChild() function that you are calling is a Promise as it has a .then() statement appended to it. What this means is that the function does not synchronously finish executing and return a value. The code below that promise is being run while the firebase function is still processing.
Give this a shot and see if it works, and if you have any further errors beyond the promise.
if(element.validation.codeunique) {
function checkCode(inputcode) {
firebaseUsers.orderByChild('code')
.equalTo(inputcode).once('value')
.then( snapshot => {
if(snapshot.val()){
return false;
} else {
return true;
}
console.log(thecode)
})
}
let message = checkCode(element.value) ? 'Code Exists':'Code Does not Exist';
}
I've done it outside of the function above and by checking it when the user submit the form, and if the code exists, i direct it to form again :
firebaseUsers.orderByChild('code')
.equalTo(mycode)
.once('value')
.then (snapshot => {
if(snapshot.val()) {
alert("Code Exists, Please Choose another");
this.props.history.push('/myscreen')
} else {
//submit the data
}
hopefully this will help someone

Byte array and JSON in [FromBody]

I am trying pass an object which consists of different data type. I am always getting null value for orderDetails in Web API.
However if do this,
purchaseOrder.Attachments = null,
in the client then orderDetails is no longer null and I have other informations like "SendEmail" and PurchaseOrderNumber.
It looks I might not be correctly set the parameter in the client (angular 2).
However testing the same Web Api method from Console app works fine and I am not getting a null value.
Do I need to separate the JSON data and byte array?
regards,
-Alan-
Models
public class Attachments
{
public int AttachmentId { get; set; }
public string FileName { get; set ;}
public byte[] FileData { get; set ;}
}
public class UpdatePurchaseOrderViewModel
{
public bool SendEmail { get; set; }
public int PurchaseOrderNumber { get; set; }
public Attachments Attachments { get; set;
}
Here is my Web API put method definition
[HttpPut("AddPurchaseOrderNumber/{purchaseOrderId}")]
public StatusCodeResult AddPurchaseOrderNumber(int purchaseOrderId, [FromBody] UpdatePurchaseOrderViewModel orderDetails)
{
try
{
var status = _service.AddPurchaseOrderNumber(purchaseOrderId, orderDetails);
if (status == 200)
_unitOfWorkAsync.SaveChanges();
else return StatusCode(status);//No Data
}
catch
{
return StatusCode(400); // Bad Request
}
return StatusCode(200);//OK
}
Typescript snippet
let headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('Accept','application/json');
let options = new RequestOptions({ headers: headers });
var body = JSON.stringify(
purchaseOrder
);
var uri = 'http://localhost:33907/api/purchaseorder/addpurchaseordernumber/' + purchaseOrderId;
return this._http.put(uri, body , options)
.map((response: Response) => {
let data = response.json();
if (data) {
return true;
}
else {
return false;
}
})
Update
The orderDetails is created as below
let file = Observable.create((observer) => {
let fr = new FileReader();
let data = new Blob([this.attachment]);
fr.readAsArrayBuffer(data);
fr.onloadend = () => {
observer.next(fr.result);
observer.complete();
};
fr.onerror = (err) => {
observer.error(err);
}
fr.onabort = () => {
observer.error("aborted");
}
});
file.map((fileData) => {
//build the attachment object which will be sent to Web API
let attachment: Attachments = {
AttachmentId: '0',
FileName: this.form.controls["attachmentName"].value,
FileData: fileData
}
//build the purchase order object
let order: UpdatePurchaseOrder = {
SendEmail: true,
PurchaseOrderNumber:this.form.controls["purchaseOrderNumber"].value * 1, //for casting purpose
Attachments: attachment
}
console.log("Loading completed");
return order;
})
When sending objects that have byte arrays as a property back and forth between a client to a WebAPI endpoint, I typically use a DTO that stores the property to explicitly define it as a Base64 string. On the server side I map the DTO to my entity by converting the Base64 string to / from the byte array for server side operations and storing in the database.
The serializer will do something like this automatically but the format passed from JavaScript may not match what the WebAPI JSON serializer is expecting (which is why it's working from your C# Console App).
You didn't include how you are creating the purchaseOrder object in your JavaScript so I can't comment on how that object is being setup - which may be where your issue is.

How to return data from Web Api controller?

Hi I am developing restfull web api application. After inserting data into database i want to return 0 for success,1 for error and data as unique id assigned to the user. I want to return above data in json format. My requirement is i have to send data to controller in json format and receive data in json format. I have following code and it is working but i want to ask few points here.
Below is my User_Creation controller code.
public result Post(Noor_Users users)
{
result obj = new result();
if (ModelState.IsValid)
{
entityObject.Noor_Users.Add(users);
int result = entityObject.SaveChanges();
if(result==1)
{
obj.success = 0;
obj.id = 5;
return obj;
}
else
{
obj.error = 1;
return obj;
}
}
else
{
obj.error = 1;
return obj;
}
}
}
My service.js file contains below code.
app.service("UserCreation", function ($http) {
this.saveSubscriber = function (sub) {
return $http({
method: 'post',
data: JSON.stringify(sub),
url: 'api/User_Creation',
contentType: "application/json"
});
}
});
This is my controller.js code.
app.controller('UserCreation', function ($scope, UserCreation) {
$scope.saveSubs = function () {
var sub = {
user_email: $scope.user_email,
user_password: $scope.user_password,
};
var saveSubs = UserCreation.saveSubscriber(sub);
saveSubs.then(function (data) {
alert(JSON.stringify(data.data));
}, function (error) {
console.log('Oops! Something went wrong while saving the data.')
})
};
});
I am expecting response in json format as below.
● status - 0 for success, 1 for failure.
● data
○ id - unique id assigned to the user
● error - error message if failed
This is working absolutelt fine. I have below line of code in webapiconfig.cs file
config.Formatters.JsonFormatter.SupportedMediaTypes
.Add(new System.Net.Http.Headers.MediaTypeHeaderValue("text/html"));
With this line of code always i can receive data in json format. But in angularjs success call i need to stringify recieved data. If all my data is returning in json then again why i should convert it to json? Also someone can tell me is above logic is a good practice to return data? Thank you.
Try the following steps:
Add this two line of code on top of your WebApiConfig.cs
public static void Register(HttpConfiguration config)
{
config.Formatters.Clear();
config.Formatters.Add(new JsonMediaTypeFormatter());
Edit you controller action with following one
public IHttpActionResult Post(Noor_Users users)
{
result obj = new result();
if (ModelState.IsValid)
{
entityObject.Noor_Users.Add(users);
int result = entityObject.SaveChanges();
if (result == 1)
{
obj.success = 0;
obj.id = 5;
}
else
{
obj.error = 1;
}
}
else
{
obj.error = 1;
}
return Ok(obj);
}

ResponseEnity with angular js

Controller code of Angular Js...
FactoryPBD.showPbdCostCompareData(data).success(
function(result) {
if(result != ""){
//doing my processing and working fine
}).error(function(result,status,message){
console.log("result" , result);
//getting undefined in all the above variable
});
Service code:
showPbdCostCompareData : function(filter) {
promise = $http({
url : 'pbd/showPbdCostCompareData?serachFilterJson='+JSON.stringify(filter),
method : "POST"
});
return promise;
}
Java Controller:-
#RequestMapping(value = "/showPbdCostCompareData", method = RequestMethod.POST)
public #ResponseBody ResponseEntity<String> showPbdCostCompareData(HttpServletRequest request,
#RequestParam String serachFilterJson) {
try {
if (null != serachFilterJson && !"".equalsIgnoreCase(serachFilterJson)) {
Gson gson = new Gson();
SearchCriteriaBean searchCriteriaObj = gson.fromJson(serachFilterJson, SearchCriteriaBean.class);
CnHeaderBean cnHeaderBean = pbdServiceImpl.getPbdCostCompareCnHeaderData(searchCriteriaObj); //getting the value from sevice
List<PbdCostCompareBean> pbdCostCompareList = null;
if (null != cnHeaderBean) {
if("F".equalsIgnoreCase(cnHeaderBean.getPbdType())){
searchCriteriaObj.setFromPartIscb(cnHeaderBean.getFromPartIscb());
searchCriteriaObj.setToPartIscb(cnHeaderBean.getToPartIscb());
pbdCostCompareList = pbdServiceImpl.getPbdCostComparisonData(searchCriteriaObj); //getting the value from sevice
}else{
return new ResponseEntity<String>("Incorrect PBD Type",HttpStatus.SERVICE_UNAVAILABLE);
}
} else {
return new ResponseEntity<String>(HttpStatus.SERVICE_UNAVAILABLE);
}
HashMap<Integer, Object> costCompareMap = new HashMap<Integer, Object>();
costCompareMap.put(1, cnHeaderBean);
costCompareMap.put(2, pbdCostCompareList);
costCompareMap.put(3, pbdServiceImpl.validateUserAccess(searchCriteriaObj, serviceUtility.getUserFromSession(request)));
String pbdDataJsonResponse = gson.toJson(costCompareMap);
return new ResponseEntity<String>(pbdDataJsonResponse, HttpStatus.OK);
} else {
return new ResponseEntity<String>(HttpStatus.SERVICE_UNAVAILABLE);
}
} catch (C2PCException e) {
return new ResponseEntity<String>(e.getMessage(),HttpStatus.SERVICE_UNAVAILABLE);
}
}
I am using Spring Rest controller with Angular js for my project. Things are working fine and data is properly sent to client side when there is no error at Java side. But in case there is an exception at java side then depending upon the exception i want to return my message to the user.My response text is not getting transmitted to the client side. Any help will be appreciated. Code is provided above
Here in above e.getMessage, i get my custom message which i have set in mu service layer and throws the exception from there. But in the client side in error message i get all the values as undefined.
I assume that in angular js when an error occurs, a JSON is expected and not html/text
So, convert the exception to json.
You can create a class
ie
class ClassErrorMessage {
private String errorCode;
private String errorMessage;
ClassErrorMessage() {
}
//getters and setters
}
and then
catch (C2PCException e) {
ClassErrorMessage classErrorMessage= new ClassErrorMessage();
classErrorMessage.setErrorCode("some code that you may want");
classErrorMessage.setErrorMessage(e.getMessage());
String error = gson.toJson(classErrorMessage);
return new ResponseEntity<String>(error,HttpStatus.SERVICE_UNAVAILABLE);
}
and let me know if this worked for you

Retrieve only one item with MVVM light in Silverlight

To grab some content from a WCF Data Service into my View Model is straight forward:
public const string RequestsPropertyName = "Requests";
private DataServiceCollection<Request> _requests = null;
public DataServiceCollection<Request> Requests
{
get { return _requests; }
set
{
if (_requests == value) { return; }
var oldValue = _requests;
_requests = value;
RaisePropertyChanged(RequestsPropertyName, oldValue, value, true);
}
}
and then
Requests.LoadAsync(query);
But what if I have a property which is not a collection?
public const string RequestDetailsPropertyName = "RequestDetails";
private Request _requestDetails = null;
public Request RequestDetails
{
get { return _requestDetails; }
and so on.
Where do I get the 'LoadAsync(query)' method from?
Thank you,
Ueli
This is a pretty simple thing to do. You just need to use the DomainContext in your application. This is where you create your query from, then apply the result to your property.
Here is an example of what this might look like in your code:
void LoadRequest(int requstID)
{
var query = workContext.GetRequestByIDQuery(requestID);
workContext.Load(query, lo =>
{
DispatcherHelper.CheckBeginInvokeOnUI(() =>
{
if (lo.HasError)
throw lo.Error;
else
RequestDetails = lo.Entities.Single();
});
}, null);
}
In this example, the workContext object is the DomainContext. The query is an specific version on the server - you can also just contruct the query client side with:
.Where(r => r.RequestID == requestID)
After the async call, it thows any errors that occurred from the async call, and then returns the only entity returned. If you get more than 1 entity, you might use .First() instead.
If this is not enough to get you going, let me know and I can explain further.

Resources