how to fix ".... validation failed" using postman with express/bodyParser - mongodb

I am making an API using express/bodyparser/MongoDB/postman, but whenever i send a POST request the Schema returns an error, how can i fix this issue?
I've tried different options in Postman, like checking if I had the right options and making sure its set to JSON.
How my requirements look:
const express = require("express");
const app = express();
const todoRoutes = require("./routes/todos");
const bodyParser = require("body-parser");
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
What my Schema looks like:
var todoSchema = new mongoose.Schema({
name: {
type: String,
required: "Use a string"
},
completed: {
type: Boolean,
default: false
},
created_date: {
type: Date,
default: Date.now
}
});
How my POST request looks:
router.post("/",function(req,res){
console.log(req.body);
db.Todo.create(req.body)
.then(function(newTodo){
res.json(newTodo);
})
.catch(function(err){
res.send(err);
});
});
The error which is returned by Postman:
{
"errors": {
"name": {
"message": "Use a string",
"name": "ValidatorError",
"properties": {
"message": "Use a string",
"type": "required",
"path": "name"
},
"kind": "required",
"path": "name"
}
},
"_message": "Todo validation failed",
"message": "Todo validation failed: name: Use a string",
"name": "ValidationError"
}
And the console.log of req.body when i give a key of name and a value of GoT :
'{\n "name" : "watch GoT"\n}': " }
The main odd thing which i see is that for some reason I get a strange log from req.body in the first place ( unusual ' and \n)

You need to go to the body tab in Postman and select xxx-w-form-urlencoded

To post a URL parameter's value, use req.params
router.post("/",function(req,res){
db.Todo.create({ name = req.params.name })
.then(function(newTodo){
res.json(newTodo);
})
.catch(function(err){
res.send(err);
});
});

Related

Sharepoint Rest API - Apply filter on expanded fields - Status 400

I am using Sharepoint rest API to get specific files in a group of folders. For this, I am applying filter on the expanded field. The problem is when I apply filter, it says the "Field or property does not exist"
I've tried to get the data without applying filter and it's coming correctly. Also, I am able to apply filter on the fields which are not under the expand parameter.
Below code is working in postman:
https://sp.foo.net/sites/spdsdfrn/_api/web/GetFolderByServerRelativeUrl('Shared Documents/abc/2019')/Folders?$expand=Files&$select=Files/Name&$filter=Files/Name eq 'abc.xlsx'
Below is the relevant part of the output:
{
"d": {
"results": [
{
"__metadata": {
"id": "https://sp.foo.net/sites/spdsdfrn/_api/web/GetFolderByServerRelativeUrl('Shared Documents/abc/2019/folder1')",
"uri": "https://sp.foo.net/sites/spdsdfrn/_api/web/GetFolderByServerRelativeUrl('Shared Documents/abc/2019/folder1')",
"type": "SP.Folder"
},
"Files": {
"results": [
{
"__metadata": {
"id": "https://sp.foo.net/sites/spdsdfrn/_api/web/GetFolderByServerRelativeUrl('Shared Documents/abc/2019/folder1/abc.xlsx')",
"uri": "https://sp.foo.net/sites/spdsdfrn/_api/web/GetFolderByServerRelativeUrl('Shared Documents/abc/2019/folder1/abc.xlsx')",
"type": "SP.File"
},
"Name": "abc.xlsx"
},
{
"__metadata": {
"id": "https://sp.foo.net/sites/spdsdfrn/_api/web/GetFolderByServerRelativeUrl('Shared Documents/abc/2019/folder1/def.xlsx')",
"uri": "https://sp.foo.net/sites/spdsdfrn/_api/web/GetFolderByServerRelativeUrl('Shared Documents/abc/2019/folder1/def.xlsx')",
"type": "SP.File"
},
"Name": "def.xlsx"
}
]
}
},
.........
.........
..........
Below code is not working in postman:
https://sp.foo.net/sites/spdsdfrn/_api/web/GetFolderByServerRelativeUrl('Shared Documents/abc/2019')/Folders?$expand=Files&$select=Files/Name&$filter=Files/Name eq 'abc.xlsx'
Below is the error output I am getting with status code 400 (bad request):
{
"error": {
"code": "-1, Microsoft.SharePoint.Client.InvalidClientQueryException",
"message": {
"lang": "en-US",
"value": "Field or property \"Name\" does not exist."
}
}
}
I've seen many solutions on the internet and they suggest that it should work in this way. Also, I've seen to check the internal names as they might differ but it's same "Name" in this case.
Is it some bug or I am missing something?
This looks like a typo:
"Field or property \"Names\" does not exist."
As your URL references "Name" not "Names".
Your second URL does not have the file type (.xlsx)
&$filter=Files/Name eq 'abc'
Otherwise...
Your URL includes "/folder". This returns a list of folders. Are you looking for a file in a particular folder, or all files by that name in any folder?
This will return a file in a particular folder:
https://sp.foo.net/sites/spdsdfrn/_api/web/GetFolderByServerRelativeUrl('Shared Documents/abc/2019')/files?$select=Name&$filter=Name eq 'abc.xlsx'
Technically speaking... It's a "server relative", not "site relative" URL. But starting with the library name seems to work.
https://sp.foo.net/sites/spdsdfrn/_api/web/GetFolderByServerRelativeUrl('Shared Documents/abc/2019')/Folders
probably should be:
https://sp.foo.net/sites/spdsdfrn/_api/web/GetFolderByServerRelativeUrl('/sites/spdsdfrn/Shared Documents/abc/2019')/Folders
You can use GetItems method in combination with setting FolderServerRelativeUrl property and Scope.
Example code:
<script src="https://code.jquery.com/jquery-1.12.4.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(function () {
var fileName="abc.xlsx";
var libraryTitle="Documents";
var folderRelativeUrl="Shared Documents/abc/2019";
var viewXml = "<View Scope='RecursiveAll'><Query><Where><Eq><FieldRef Name='FileLeafRef'/><Value Type='File'>"+fileName+"</Value></Eq></Where></Query></View>";
var url = _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getbytitle('"+libraryTitle+"')/getitems?$select=*,FileDirRef,FileRef";
var query = {
'query' : {
'__metadata': { 'type': 'SP.CamlQuery' },
'ViewXml' : viewXml,
'FolderServerRelativeUrl': folderRelativeUrl
}
};
$.ajax({
url: url,
method: "POST",
data: JSON.stringify(query),
headers: {
"X-RequestDigest": $("#__REQUESTDIGEST").val(),
"Accept": "application/json; odata=verbose",
"content-type": "application/json; odata=verbose"
},
success: function (data) {
alert(JSON.stringify(data.d.results));
},
error: function (err) {
alert(JSON.stringify(err));
}
});
});
</script>
Or we can use the REST API below.
/_api/web/lists/getbytitle('Documents')/items?$select=File&$expand=File&$filter=FileLeafRef eq 'abc.xlsx'

Include Loopback relation in POST response

I have a working chat-room loopback project, which also utilises Socket.IO.
Once I create a Message (POST to Loopback REST API), I need the response the include the 'creator' relation.
This works fine when using GET, but I cannot include the relation to the POST response.
I'm sure it's a simple remote hook, but I'm stuck...
Any help is greatly appreciated!
"relations": {
"creator": {
"type": "belongsTo",
"model": "Person",
"foreignKey": "",
"options": {
"nestRemoting": true
}
},
"event": {
"type": "belongsTo",
"model": "Event",
"foreignKey": "",
"options": {
"nestRemoting": true
}
}
},
There are two options how you can do it with Loopback 2.x or 3.x (not sure about the Loopback 4.x).
Let's assume we have the following "Note" model:
{
"name": "Note",
"properties": {
"title": {
"type": "string",
"required": true
},
"content": {
"type": "string"
},
"userId": {
"type": "number"
}
},
"relations": {
"user": {
"type": "belongsTo",
"model": "User",
"foreignKey": "userId"
}
}
}
Now, to include "user" property (which is a belongsTo relation of Note) in the response when you create (POST) a Note you have two options.
Option #1 (Recommended): Create a custom remote method and hide the default method in your model's script file. In this case your note.js file should look something like:
module.exports = function (Note) {
// Hide the default 'create' remote method
Note.disableRemoteMethod('create', true);
// Add a custom 'customCreate' remote method
Note.remoteMethod('customCreate', {
description: 'Create a new instance of the model and persist it into the data source.',
accessType: 'WRITE',
accepts: [
{
arg: 'data',
type: 'object',
model: 'Note',
allowArray: true,
description: 'Model instance data',
http: { source: 'body' },
},
{ arg: 'options', type: 'object', http: 'optionsFromRequest' },
],
returns: { arg: 'data', type: 'Note', root: true },
http: { verb: 'post', path: '/' },
isStatic: true,
});
Note.customCreate = function (data, options, cb) {
Note.create(data, options, function(err, newObj) {
if (err) {
cb(err);
}
else {
// here we try to load the user value
newObj.user(function (err, user) {
if (user) {
// if we found a user we add it to __data, so it appears in the output (a bit hacky way)
newObj.__data.user = user;
}
cb(err, newObj);
});
}
});
};
};
I would recommend using this option because you achieve what you need with minimal changes in the default logic of the loopback model, i.e. all the default methods like create, upsert, etc. continue to have default behavior.
Option 2: Use 'after save' operation hook (be careful with this approach as it changes the way how create, upsert, upsertWithWhere and other default methods work)
In this case your note.js file should look something like:
module.exports = function (Note) {
Note.observe('after save', function (ctx, next) {
ctx.instance.user(function (err, user) {
ctx.instance.__data.user = user;
next();
});
});
};
The second option has less code, but as I mentioned before you should be very careful using it because it will change the behavior of default "create" method of the model. I.e. 'after save' action will be executed each time you call Model.create, Model.upsert, etc. It will also slow down these operation as you add additional select query in the 'after save' hook.

Azure Machine Learning REST API: no body

I am simply strying to call the REST API end point of a machine learning experiment created with Azure. I keep getting this error message:
{
"error": {
"code": "BadArgument",
"message": "Invalid argument provided.",
"details": [
{
"code": "RequestBodyInvalid",
"message": "No request body provided or error in deserializing the request body."
}
]
}
}
I have looked it up on their documentation: https://learn.microsoft.com/en-us/azure/machine-learning/machine-learning-web-service-error-codes
All it says is that my bod is empty, I am not sure how can it be empty, here is my code:
router.post('/rating/new', function(req, res) {
var postData = {
"Inputs": {
"input2":
[
{
'Col1': "A11",
'Col2': "6",
'Col3': "A34",
'Col4': "A43",
'Col5': "1169",
'Col6': "A65",
'Col7': "A75",
'Col8': "4",
'Col9': "A93",
'Col10': "A101",
'Col11': "4",
'Col12': "A121",
'Col13': "67",
'Col14': "A143",
'Col15': "A152",
'Col16': "2",
'Col17': "A173",
'Col18': "1",
'Col19': "A192",
'Col20': "A201",
'Col21': "1",
}
],
},
"GlobalParameters": {
}
};
// Configure the request
var options = {
url: config.ML_PREDICTIVE.url,
method: 'POST',
headers: {
'Content-Type':'application/json',
'Authorization':('Bearer ' + config.ML_PREDICTIVE.apiKey)},
form: postData
}
console.log(JSON.stringify(options));
// Start the request
request.post(options, function (error, response, body) {
if(error){
res.status(403).send(error);
}
if(response.statusCode != 200){
res.status(403).send(response.body);
}
if (!error && response.statusCode == 200) {
console.log(body)
}
})
});
The only thing I see that could go wrong is that "form" in the request is not considered body by azure, I have tried with "body" as well no success.
Please help !
According to the code you provided, the variable postData is not valid JSON string. You'd need to use JSON.stringify() method to convert postData value to a JSON string before you send a POST request.

Joi validate individual fields of nested schema

I have a nested schema setup like this:
var schema = Joi.object().keys({
first_name: Joi.string().required(),
last_name: Joi.string().required(),
address: Joi.object().keys({
street: Joi.string().required(),
zip: Joi.number().required(),
state: Joi.string().required(),
country: Joi.string().required()
}).required(),
})
var options = { abortEarly: false };
var result = Joi.validate({}, schema, options);
When running this, result.error will return the message:
[
{message: '"first_name" is required', path: 'first_name' },
{message: '"last_name" is required', path: 'last_name' },
{message: '"address" is required', path: 'address' }
]
As you see, the address field is not expanded. I don't want to get a message that the whole address field is missing. Instead, I want to be informed about the individual items in the address schema missing. When I don't make address explicitly required, the items in it don't get validated against required() at all. The nested field validation seems to work only on the entire nested schema object level, not on the individual items within the schema level. How do I make it work with the individual nested schema items?
Adding a "skeleton" object works.
Working example here.
import Joi, {
string,
number,
object
} from "joi";
var schema = object({
first_name: string().required(),
last_name: string().required(),
address: object({
street: string().required(),
zip: number().required(),
state: string().required(),
country: string().required()
})/*.required(), <= Not needed */
})
var skeleton = { address: {} };
var options = { abortEarly: false };
var validate = data => {
var newData = Object.assign({}, skeleton, data);
return Joi.validate( newData, schema, options);
}
console.log(
JSON.stringify(validate({}).error.details, null, 2)
);
Result:
[
{
"message": "\"first_name\" is required",
"path": "first_name",
"type": "any.required",
"context": {
"key": "first_name"
}
},
{
"message": "\"last_name\" is required",
"path": "last_name",
"type": "any.required",
"context": {
"key": "last_name"
}
},
{
"message": "\"street\" is required",
"path": "address.street",
"type": "any.required",
"context": {
"key": "street"
}
},
{
"message": "\"zip\" is required",
"path": "address.zip",
"type": "any.required",
"context": {
"key": "zip"
}
},
{
"message": "\"state\" is required",
"path": "address.state",
"type": "any.required",
"context": {
"key": "state"
}
},
{
"message": "\"country\" is required",
"path": "address.country",
"type": "any.required",
"context": {
"key": "country"
}
}
]

Add event to calendar on SharePoint through REST API

I'm trying to add a calendar event to a SharePoint Calendar through REST API but i can't seems to find the relevant resources to achieve this.
If i understand correctly, the calendar in SharePoint is a List of events object, as such I should be able to add the event via ListItem object?
Sorry if this sounds wrong as I'm not familiar with SharePoint structure.
Thanks
This is the example for OAuth token Authentication but REST part is anyway like this.
var dataObj = {
"Subject": "Birthday Party"
"Body": {
"ContentType": "Text",
"Content": "Birthday Party for Cathy",
},
"Start": {
"dateTime": "2016-07-03T09:00:00Z",
"timeZone": "Asia/Tokyo"
},
"End": {
"dateTime": "2016-07-04T11:00:00Z",
"timeZone": "Asia/Tokyo"
},
"Location": {
"DisplayName": "Conference Room 1"
},
"ShowAs": "Busy",
"Attendees": [
{
"EmailAddress": { "Name": "Alex Darrow", "Address": "darrow.alex#company.com" },
"Type": "Required"
}
]
};
var url = "https://graph.microsoft.com/v1.0/me/events/";
var data = JSON.stringify(dataObj);
$.ajax({
url: url,
type: "POST",
data: data,
beforeSend: function (XMLHttpRequest) {
XMLHttpRequest.setRequestHeader("Accept", "application/json;odata.metadata=full;odata.streaming=true");
XMLHttpRequest.setRequestHeader('Authorization', 'Bearer ' + accessToken);
XMLHttpRequest.setRequestHeader("content-type", "application/json;odata=verbose");
},
success: function (result, textStatus, jqXHR) {
//Success
},
error: function (data) {
//
}});