Send array from javascript to Spring Controller - javascript

I have a javascript function that makes a post to a controller API. Here´s the code:
exports.importList = function (req, res) {
res.setHeader('Content-Type', 'application/json');
var agencyId = req.user.agency_id;
var userId = req.user.id;
data = {
id_list: req.body.ids,
remoteHost:'127.0.0.1',
userId : userId,
agencyId:agencyId
};
call = '/ilist/importer/list/'; //Spring route
fetcher.post(call, 'post', data, function (err, result) {
console.log(data);
})
}
req.body.ids is an array of string values, so the data I want to send to my Controller has this structure:
{ id_list: [ '2147041', '2155271' ],
remoteHost: '127.0.0.1',
userId: 'user',
agencyId: 1 }
My controller method:
#RequestMapping(value="/list/", method = RequestMethod.POST, headers = "Accept=application/json")
public #ResponseBody RemaxResponse importPropertyList(#RequestBody ArrayList<String> data ) {
List<Long> ids = new ArrayList<>();
for (String id : data.id_list) {
ids.add(Long.valueOf(id));
}
response = ilistIImporterService.importPropertyList(ids);
return response;
}
I need to take in my Controller the array of strings and store it in an array of integer, and the other parameters store in integer variables.
Now, I'm getting that the data I send from javascript is sintactically incorrect. What's the proper way to do this?

If you want to send the whole object, I'd create a pojo and use that as #RequestBody like
public #ResponseBody RemaxResponse importPropertyList(#RequestBody RequestObject data ) {
Now spring can parse the whole data nicely to the given pojo, and you can simply use the getters to obtain the data you need.
A pojo could look like
public class RequestObject {
private List<Long> idList = null;
private String remoteHost;
private String userId;
private Integer agencyId;
public List<Long> getIdList() {
return idList;
}
public void setIdList(List<Long> idList) {
this.idList = idList;
}
public String getRemoteHost() {
return remoteHost;
}
public void setRemoteHost(String remoteHost) {
this.remoteHost = remoteHost;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public Integer getAgencyId() {
return agencyId;
}
public void setAgencyId(Integer agencyId) {
this.agencyId = agencyId;
}
}

Related

400 Bad request when trying to fetch from SpringBoot using React

I try to delete an entity with a given id. However, when I try to fetch from my API, i get a 400 bad request error.
async deleteFood(foodId) {
const params = {
'id' : foodId
}
const rawResponse = await fetch("food/delete", {
method:"POST",
headers: {'Content-Type': 'application/json'},
body: params,
});
const content = await rawResponse.json();
}
In my SpringBoot log, it shows me the id parameter is missing:
WARN 7784 --- [nio-8080-exec-7] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.bind.MissingServletRequestParameterException: Required request parameter 'id' for method parameter type int is not present]
I already tried putting params into JSON.stringify(), but this doesn't change anything.
Controller code:
#PostMapping(path = "/delete")
public #ResponseBody int deleteById(#RequestParam int id) {
if (foodRepository.existsById(id)) {
foodRepository.deleteById(id);
return Response.SC_ACCEPTED;
}
return Response.SC_BAD_REQUEST;
}
You are sending the data via body, but in the controller you are waiting that as a #RequestParam
#PostMapping(path = "/delete")
public #ResponseBody int deleteById(#RequestParam int id) {
if (foodRepository.existsById(id)) {
foodRepository.deleteById(id);
return Response.SC_ACCEPTED;
}
return Response.SC_BAD_REQUEST;
}
You need to either change the way you receive id param (#RequestBody instead of #RequestParam) some like:
#PostMapping(path = "/delete")
public #ResponseBody int deleteById(#RequestBody int id) {
if (foodRepository.existsById(id)) {
foodRepository.deleteById(id);
return Response.SC_ACCEPTED;
}
return Response.SC_BAD_REQUEST;
}
or change the way you're sending from React (send it as a url param)

Process web API callback's response after window.location.href redirect

I have a Web Api which handles OpenId sign in such way:
[HttpGet]
[AllowAnonymous]
[Route("ExternalLogin", Name = "ExternalLogin")]
public async Task<IActionResult> ExternalLogin(string provider, string returnUrl = "")
{
ApplicationUser user = await GetAuthUser();
string userId = user?.Id;
var properties = _externalSignInService.ConfigureExternalAuthenticationProperties(provider, Url.Action("ExternalCallback", "Account", new { returnUrl, userId }));
return Challenge(properties, provider);
}
This is called from Angular app with JS redirect function (it is hardcoded, because I am trying to make it works firstly).
public loginExternal() {
window.location.href = `https://localhost:5001/v1/account/ExternalLogin?provider=Steam&returnUrl=${window.location.href}`;
}
After Steam login success, it makes to callback method specified there Url.Action(...)
[HttpGet]
[AllowAnonymous]
[Route("Steam", Name = "ExternalCallback")]
public async Task<ActionResult<LoginResponseDto>> ExternalCallback(string error = null, string returnUrl = "", string userId = null)
{
if (error != null)
{
return Redirect(returnUrl + "/unauthorized");
}
...sign in duties...
return ProduceLoginResponse(signInResult);
}
private ActionResult<LoginResponseDto> ProduceLoginResponse((AppSignInResult result, SignInData data) loginResults)
{
var (result, data) = loginResults;
return result switch
{
AppSignInResult.Success => Ok(new LoginResponseDto()
{
AccessToken = data.Token.AccessToken,
TokenType = data.Token.TokenType,
ExpiresIn = data.Token.GetRemainingLifetimeSeconds(),
Username = data.Username,
Email = data.Email,
IsExternalLogin = data.IsExternalLogin,
ExternalAuthenticationProvider = data.ExternalAuthenticationProvider
}),
_ => throw new InvalidEnumArgumentException($"Unknown sign-in result '{result}'.")
};
}
So in my Angular app I need to process this data (save JWT token in storage, etc..). How to do it keeping in mind that I used window.location.href redirect?
I've figured it out with saving user sign in data in HttpContext.Session storage and changing return approach from return ProduceLoginResponse(signInResult); to return Redirect(returnHost + "/sign-in"); and after redirect, in angular SignIn component inside ngOnInit method I am calling another endpoint to get my sign in data from HttpContext.Session storage.
[HttpGet]
[AllowAnonymous]
[Route("sign-in")]
public ActionResult<object> ProvideSignInDataFromSession()
{
var sessionData = HttpContext.Session.GetString(SignInDataKey);
if (sessionData != null)
{
var data = JsonConvert.DeserializeObject<SignInData>(sessionData);
return Ok(new
{
user = data.Username,
access_token = data.Token.AccessToken,
token_type = data.Token.TokenType,
expires_in = data.Token.GetRemainingLifetimeSeconds(),
});
}
return Redirect(CORS.CORS.returnOrigin + "/unauthorized");
}

Send array json to controller web api c#

I have a web api controller, but i got the object myJson null.
[HttpPost]
[Route("api/Torneo/AddEquipos")]
public JsonResult InsertTorneoEquipos([FromBody]EquiposTorneo myJson)
{
return new JsonResult("OK");
}
I send this object json in my front-end
myJson =
[
{\"id_torneo\":1,\"id_equipo\":27},{\"id_torneo\":1,\"id_equipo\":28}
]
Model EquiposTorneo
public class EquiposTorneo
{
public int id_torneo { get; set; }
public int id_equipo { get; set; }
}
My front-end vuejs:
registrar () {
const params = this.rowData
const myJson = JSON.stringify(params)
axios.post(url + 'Torneo/AddEquipos', {
myJson,
})
.then((response) => {
console.log(response)
})
You can try following.
[FromBody]List<EquiposTorneo> myJson
If there is single item then single object and if array then List or Enumrable required.

how to integrate asp.net mvc 5 with latest Paypal checkout .net sdk v2?

I tried to use Paypal Checkout SDK V2 in my Asp.Net MVC 5 project with .Net Framework 4.7.2 the but this seems to be something missing or wrong from my side.
I am just trying to integrate Paypal Checkout sdk and want to create an order so that my payment 'll be proceed by some paypal user and I only want to show one Pay Now button.
The SDK link is here:
https://github.com/paypal/Checkout-NET-SDK
and followed these links
https://developer.paypal.com/docs/checkout/reference/server-integration/get-transaction/#on-the-client
https://developer.paypal.com/demo/checkout/#/pattern/server
This is my code for trying it
C# Code
public class CheckoutController : Controller
{
public ActionResult Index()
{
ViewBag.ClientId = PayPalClient.ClientId;
ViewBag.CurrencyCode = "GBP"; // Get from a data store
ViewBag.CurrencySign = "£"; // Get from a data store
return View();
}
//[Route("api/paypal/checkout/order/create")]
public async static Task<HttpResponse> createOrder()
{
HttpResponse response;
// Construct a request object and set desired parameters
// Here, OrdersCreateRequest() creates a POST request to /v2/checkout/orders
var order = new OrderRequest()
{
CheckoutPaymentIntent = "CAPTURE",
PurchaseUnits = new List<PurchaseUnitRequest>()
{
new PurchaseUnitRequest()
{
AmountWithBreakdown = new AmountWithBreakdown()
{
CurrencyCode = "USD",
Value = "100.00"
}
}
},
ApplicationContext = new ApplicationContext()
{
ReturnUrl = "https://www.example.com",
CancelUrl = "https://www.example.com"
}
};
// Call API with your client and get a response for your call
var request = new OrdersCreateRequest();
request.Prefer("return=representation");
request.RequestBody(order);
response = await PayPalClient.Client().Execute(request);
var statusCode = response.StatusCode;
Order result = response.Result<Order>();
Console.WriteLine("Status: {0}", result.Status);
Console.WriteLine("Order Id: {0}", result.Id);
Console.WriteLine("Intent: {0}", result.CheckoutPaymentIntent);
Console.WriteLine("Links:");
foreach (LinkDescription link in result.Links)
{
Console.WriteLine("\t{0}: {1}\tCall Type: {2}", link.Rel, link.Href, link.Method);
}
return response;
}
public async static Task<HttpResponse> captureOrder()
{
// Construct a request object and set desired parameters
// Replace ORDER-ID with the approved order id from create order
var request = new OrdersCaptureRequest("APPROVED-ORDER-ID");
request.RequestBody(new OrderActionRequest());
HttpResponse response = await PayPalClient.Client().Execute(request);
var statusCode = response.StatusCode;
Order result = response.Result<Order>();
Console.WriteLine("Status: {0}", result.Status);
Console.WriteLine("Capture Id: {0}", result.Id);
return response;
}
/// <summary>
/// This action is called when the user clicks on the PayPal button.
/// </summary>
/// <returns></returns>
//[Route("api/paypal/checkout/order/create")]
public async Task<SmartButtonHttpResponse> Create()
{
var request = new PayPalCheckoutSdk.Orders.OrdersCreateRequest();
request.Prefer("return=representation");
request.RequestBody(OrderBuilder.Build());
// Call PayPal to set up a transaction
var response = await PayPalClient.Client().Execute(request);
// Create a response, with an order id.
var result = response.Result<PayPalCheckoutSdk.Orders.Order>();
var payPalHttpResponse = new SmartButtonHttpResponse(response)
{
orderID = result.Id
};
return payPalHttpResponse;
}
/// <summary>
/// This action is called once the PayPal transaction is approved
/// </summary>
/// <param name="orderId"></param>
/// <returns></returns>
//[Route("api/paypal/checkout/order/approved/{orderId}")]
public ActionResult Approved(string orderId)
{
return Json("Sucess", JsonRequestBehavior.AllowGet);
}
/// <summary>
/// This action is called once the PayPal transaction is complete
/// </summary>
/// <param name="orderId"></param>
/// <returns></returns>
//[Route("api/paypal/checkout/order/complete/{orderId}")]
public ActionResult Complete(string orderId)
{
// 1. Update the database.
// 2. Complete the order process. Create and send invoices etc.
// 3. Complete the shipping process.
return Json("Completed", JsonRequestBehavior.AllowGet);
}
/// <summary>
/// This action is called once the PayPal transaction is complete
/// </summary>
/// <param name="orderId"></param>
/// <returns></returns>
//[Route("api/paypal/checkout/order/cancel/{orderId}")]
public ActionResult Cancel(string orderId)
{
// 1. Remove the orderId from the database.
return Json("Cancel", JsonRequestBehavior.AllowGet);
}
/// <summary>
/// This action is called once the PayPal transaction is complete
/// </summary>
/// <param name="orderId"></param>
/// <returns></returns>
//[Route("api/paypal/checkout/order/error/{orderId}/{error}")]
public ActionResult Error(string orderId,
string error)
{
// Log the error.
// Notify the user.
string temp = System.Web.HttpUtility.UrlDecode(error);
return Json(temp, JsonRequestBehavior.AllowGet);
}
}
public static class OrderBuilder
{
/// <summary>
/// Use classes from the PayPalCheckoutSdk to build an OrderRequest
/// </summary>
/// <returns></returns>
public static OrderRequest Build()
{
// Construct a request object and set desired parameters
// Here, OrdersCreateRequest() creates a POST request to /v2/checkout/orders
OrderRequest order = new OrderRequest()
{
CheckoutPaymentIntent = "CAPTURE",
PurchaseUnits = new List<PurchaseUnitRequest>()
{
new PurchaseUnitRequest()
{
AmountWithBreakdown = new AmountWithBreakdown()
{
CurrencyCode = "USD",
Value = "100.00"
}
}
},
ApplicationContext = new ApplicationContext()
{
ReturnUrl = "https://www.example.com",
CancelUrl = "https://www.example.com"
}
};
// Call API with your client and get a response for your call
var request = new OrdersCreateRequest();
request.Prefer("return=representation");
request.RequestBody(order);
return order;
}
}
public class PayPalClient
{
public static string ClientId = " your client id";
public static string Secrets = "your client secret";
public static string SandboxClientId { get; set; } =
"<alert>{SandboxClientId}</alert>";
public static string SandboxClientSecret { get; set; } =
"<alert>{SandboxClientSecret}</alert>";
public static string LiveClientId { get; set; } =
"<alert>{PayPal LIVE Client Id}</alert>";
public static string LiveClientSecret { get; set; } =
"<alert>{PayPal LIVE Client Secret}</alert>";
public static PayPalEnvironment Environment()
{
//return new SandboxEnvironment("<alert>SandboxClientId</alert>",
// "<alert>SandboxClientSecret</alert>");
return new SandboxEnvironment(ClientId, Secrets);
}
public static PayPalCheckoutSdk.Core.PayPalHttpClient Client()
{
return new PayPalHttpClient(Environment());
}
public static PayPalCheckoutSdk.Core.PayPalHttpClient Client(string refreshToken)
{
return new PayPalHttpClient(Environment(), refreshToken);
}
public static String ObjectToJSONString(Object serializableObject)
{
MemoryStream memoryStream = new MemoryStream();
var writer = JsonReaderWriterFactory.CreateJsonWriter(memoryStream,
Encoding.UTF8,
true,
true,
" ");
var ser = new DataContractJsonSerializer(serializableObject.GetType(),
new DataContractJsonSerializerSettings
{
UseSimpleDictionaryFormat = true
});
ser.WriteObject(writer,
serializableObject);
memoryStream.Position = 0;
StreamReader sr = new StreamReader(memoryStream);
return sr.ReadToEnd();
}
}
public class SmartButtonHttpResponse
{
readonly PayPalCheckoutSdk.Orders.Order _result;
public SmartButtonHttpResponse(PayPalHttp.HttpResponse httpResponse)
{
Headers = httpResponse.Headers;
StatusCode = httpResponse.StatusCode;
_result = httpResponse.Result<PayPalCheckoutSdk.Orders.Order>();
}
public HttpHeaders Headers { get; }
public HttpStatusCode StatusCode { get; }
public PayPalCheckoutSdk.Orders.Order Result()
{
return _result;
}
public string orderID { get; set; }
}
View html is
<!-- Set up a container element for the PayPal smart button -->
<div id="paypal-button-container"></div>
#section scripts
{
<script src="https://www.paypal.com/sdk/js?client-id=#ViewBag.ClientId"></script>
<script type="text/javascript">
var orderId;
function httpGet(url) {
var xmlHttp = new XMLHttpRequest();
xmlHttp.open("GET", url, false);
xmlHttp.send(null);
return xmlHttp.responseText;
}
paypal.Buttons({
// Set up the transaction
enableStandardCardFields: true,
createOrder: function (data, actions) {
orderId = data.orderID;
console.log("Start");
console.log(data);
console.log(actions);
console.log("End");
return fetch(
'/PaypalPayments/create/', {
method: 'post'
}).then(function (res) {
return res.json();
}).then(function (data) {
return data.orderID;
});
},
// Finalise the transaction
onApprove: function (data, actions) {
return fetch('/PaypalPayments/approved/' + data.orderID, {
method: 'post'
}).then(function (res) {
return actions.order.capture();
}).then(function (details) {
// (Preferred) Notify the server that the transaction id complete
// and have an option to display an order completed screen.
window.location.replace('/PaypalPayments/complete/' +
data.orderID + '/#ViewBag.CurrencyCode');
// OR
// Notify the server that the transaction id complete
//httpGet('/api/paypal/checkout/order/complete/' + data.orderID);
// Show a success message to the buyer
alert('Transaction completed by ' + details.payer.name.given_name + '!');
});
},
// Buyer cancelled the payment
onCancel: function (data, actions) {
httpGet('/PaypalPayments/cancel/' + data.orderID);
},
// An error occurred during the transaction
onError: function (err) {
debugger;
fetch(
'/PaypalPayments/error/', {
method: 'post',
headers: { 'Content-type': 'application/json' },
body: JSON.stringify({ orderId: orderId, error: encodeURIComponent(err)})
}).then(function (res) {
return res.json();
}).then(function (data) {
return data.orderID;
});
}
}).render('#paypal-button-container');
</script>
}
The error which I 'll have to receive is given below:
My create post request is successful by returning 200 status.
After this request, the control instantly goes to Error function and throwing this error.
Error: Unexpected token P in JSON at position 0"
The complete error detail is mentioned below
SyntaxError: Unexpected token P in JSON at position 0
Error: Unexpected token P in JSON at position 0
at Qt.error (https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:60544)
at Object.<anonymous> (https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:68311)
at JSON.parse (<anonymous>)
at o (https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:68170)
at dr (https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:68323)
at u.on (https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:72994)
at br (https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:73131)
at https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:79250
at Function.n.try (https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:14118)
at https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:79047
Error: Unexpected token P in JSON at position 0
at Qt.error (https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:60544)
at Array.<anonymous> (https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:68311)
at JSON.parse (<anonymous>)
at o (https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:68170)
at dr (https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:68323)
at u.on (https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:72994)
at br (https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:73131)
at https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:79250
at Function.n.try (https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:14118)
at https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:79047
Can anybody guide me properly? I tried different articles but I am still getting these errors.
When you fetch /PaypalPayments/create/ from your server , what do you get back?
Obviously you aren't getting back valid JSON, but your code is trying to parse it as JSON.
Change your server code to only give back valid JSON. The code actually seems okay, so perhaps there is something wrong with the /PayPalPayments/create/ route that is hardcoded in the client-side code.
It would also be wise to change your client-side code to follow the best sample available, which is at https://developer.paypal.com/demo/checkout/#/pattern/server and demonstrates how to properly handle errors for the capture
(Just noticed the code in your example uses actions.order.capture() combined with this server-side integration, which is rather awful -- seems the server-side captureOrder task never even gets called, which is rather the whole point of using server-side APIs in the first place, if you don't capture from the server you get none of the benefits)

Receiving Two Objects in req.body

I am receiving a POST request from an Unity app in x-form-encoded format into my NodeJs web-server .
I use app.use(bodyParser.urlencoded({ extended: true})) , to parse the content . But the req.body returns two objects , problem is that I cannot access the property of an individual property since they are neither wrapped in an array or object .
On console.log(req.body)
I get the following result
{ sessionId: '5ujgp6vwk1pivth4', gameId: '1', level: '0', score: '0' }
{ sessionId: '5ujgp6vwk1pivth4', gameId: '2', level: '0', score: '0' }
I want to know which type of datatype is this and how will I be able to access a particular property , suppose if I do
console.log(req.body.sessionId) , I get
5ujgp6vwk1pivth4
5ujgp6vwk1pivth4
Even if I try to push it into an array I still get the same result .
I am trying to fetch these objects into an array so that it will be easier for me to access them .
The script for the Express routes :
const express = require('express')
const path = require('path')
const hbs = require('hbs')
const bodyParser = require('body-parser')
const viewsRouter = require('./routers/views')
const apiRouter = require('./routers/api')
const cookieParser = require('cookie-parser')
require ('./db/mongoose')
const app = express()
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true}))
app.use(cookieParser())
const publicDirectoryPath = path.join(__dirname,'../public')
app.use(express.static(publicDirectoryPath))
const viewsPath = path.join(__dirname,'../templates/views')
const partialsPath = path.join(__dirname,'../templates/partials')
hbs.registerPartials(partialsPath)
hbs.registerHelper('ifCond', function(v1, v2, options) {
if(v1 === v2) {
return options.fn(this);
}
return options.inverse(this);
});
hbs.registerHelper("math", function(lvalue, operator, rvalue, options) {
lvalue = parseFloat(lvalue);
rvalue = parseFloat(rvalue);
return {
"+": lvalue + rvalue,
"-": lvalue - rvalue,
"*": lvalue * rvalue,
"/": lvalue / rvalue,
"%": lvalue % rvalue
}[operator];
});
app.use(viewsRouter)
app.use(apiRouter)
// For any of the un-handled routes
app.get('*',(req,res)=>{
res.render('error')
})
//Setting up the CORS functionality in Express for Making AJAX calls
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
app.set('views',viewsPath)
app.set('view engine','hbs')
app.listen(80,()=>{
console.log('Server Started on Port 80')
})
The Route responsible for the particular POST is
apiRouter.post('/api/updateScore/',async(req,res)=>{
console.log(req.body)
})
The client script is :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine;
using UnityEngine.Networking;
using System.Collections;
using UnityEngine.SceneManagement;
using System.Text;
public class ScoreSender : MonoBehaviour {
public Authentication authentication;
public static readonly string scoreUrl = "https://eyenet.pythonanywhere.com/scores/";
public static ScoreSender instance;
public string Address = "127.0.0.1:8000";
// Use this for initialization
void Start () {
instance = this;
}
// Update is called once per frame
void Update () {
}
public void sendScore(int gameId, int level)
{
}
public void sendScore(string gameId, int level, int score)
{
string loginURL = Address+ "/api/updateScore/";
WWWForm form = new WWWForm();
form.AddField( "sessionId", authentication.session );
Dictionary<string, string> headers = form.headers;
byte[] rawData = form.data;
WWW www = new WWW(loginURL, rawData, headers);
}
// StartCoroutine(WaitForRequest(www));
public void saveScore(string gameId, int nextlevel, int score)
{
// get session id
string sessionCode = authentication.session;
// get score array
int noOfGames = PlayerPrefs.GetInt("totalGames",0);
// get or create score, level, nextlevel arrays
int gid = int.Parse(gameId);
//
int[] scoreArray = PlayerPrefsX.GetIntArray(sessionCode+"scores",0,noOfGames+1);
int[] nextLevelsArray = PlayerPrefsX.GetIntArray(sessionCode+"nextLevels",0,noOfGames+1);
nextLevelsArray[gid] = nextlevel;
scoreArray[gid] = score;
PlayerPrefsX.SetIntArray(sessionCode+"scores",scoreArray);
PlayerPrefsX.SetIntArray(sessionCode+"nextLevels",nextLevelsArray);
PlayerPrefsX.SetIntArray("gameLevels",nextLevelsArray);
Debug.Log("saved score and nextLevels offline");
}
//for sending score to the cloud
public void uploadScore()
{
//testing
//StartCoroutine(scoreSend(authentication.session,"1",45,34));
syncScore(authentication.session);
}
//for online sessions only
void syncScore(string sessionId)
{
Debug.Log("We are syncing the score for this session");
int noOfGames = PlayerPrefs.GetInt("totalGames",0);
int[] currentGamePlays = PlayerPrefsX.GetIntArray(sessionId+"currentGamePlays",0,noOfGames);
int[] scoreArray = PlayerPrefsX.GetIntArray(sessionId+"scores",0,noOfGames+1);
int[] nextLevelsArray = PlayerPrefsX.GetIntArray(sessionId+"nextLevels",0,noOfGames+1);
for(int i=0;i<noOfGames+1;i++)
{
if(currentGamePlays[i]==1) //if the game is played in this session
{
StartCoroutine( scoreSend(sessionId,""+i,nextLevelsArray[i],scoreArray[i]));
Debug.Log("score:"+scoreArray[i]);
Debug.Log("level:"+nextLevelsArray[i]);
}
}
}
public int noOfScores=0;
public void syncOfflineScore(int num,string actualId)
{
string sessionId = "offlineSession"+num;
int noOfGames = PlayerPrefs.GetInt("totalGames",0);
int[] currentGamePlays = PlayerPrefsX.GetIntArray(sessionId+"currentGamePlays",0,noOfGames+1);
int[] scoreArray = PlayerPrefsX.GetIntArray(sessionId+"scores",0,noOfGames+1);
int[] nextLevelsArray = PlayerPrefsX.GetIntArray(sessionId+"nextLevels",0,noOfGames+1);
for(int i=0;i<noOfGames+1;i++)
{
if(currentGamePlays[i]==1) //if the game is played in this session
{
noOfScores++;
}
}
for(int i=0;i<noOfGames+1;i++)
{
if(currentGamePlays[i]==1) //if the game is played in this session
{
StartCoroutine( offlineScoreSend(actualId,""+i,nextLevelsArray[i],scoreArray[i]));
Debug.Log("score:"+scoreArray[i]);
Debug.Log("level:"+nextLevelsArray[i]);
}
}
}
//working fine
IEnumerator scoreSend(string sessionId,string gameId,int nextlevel, int score)
{
string scoreUrl = authentication.Address+ "/api/updateScore/";
WWWForm form = new WWWForm();
form.AddField( "sessionId", sessionId );
form.AddField( "gameId", gameId );
form.AddField( "level", nextlevel);
form.AddField( "score", score);
Dictionary<string, string> headers = form.headers;
//Dictionary<string, string> headers = new Dictionary<string, string>();
//headers.Add("Content-Type", "application/json");
byte[] rawData = form.data;
WWW www = new WWW(scoreUrl, rawData, headers);
WWW data =www;
yield return data;
if(data.error!=null)
{
Debug.Log (data.error);
if(data.error == "Cannot connect to destination host")
{
}
}
else
{
Debug.Log(data.text);
ServerResponse res = JsonUtility.FromJson<ServerResponse>(data.text);
if(res.status==0)
{
Debug.Log("Updated score");
}
else
{
Debug.Log("Got an error");
}
}
}
//test it
IEnumerator offlineScoreSend(string sessionId,string gameId,int nextlevel, int score)
{
string scoreUrl = authentication.Address+ "/api/updateScore/";
WWWForm form = new WWWForm();
form.AddField( "sessionId", sessionId );
form.AddField( "gameId", gameId );
form.AddField( "level", nextlevel);
form.AddField( "score", score);
Dictionary<string, string> headers = form.headers;
byte[] rawData = form.data;
WWW www = new WWW(scoreUrl, rawData, headers);
WWW data =www;
yield return data;
if(data.error!=null)
{
Debug.Log (data.error);
if(data.error == "Cannot connect to destination host")
{
}
}
else
{
Debug.Log(data.text);
ServerResponse res = JsonUtility.FromJson<ServerResponse>(data.text);
if(res.status==0)
{
Debug.Log("Updated score");
noOfScores--;
if(noOfScores==0)
{
authentication.syncOfflineSessionsDataComplete();
}
}
else
{
Debug.Log("Got an error");
}
}
}
}
Unfortunately, what is happening is different than what you think is happening, and there isn't enough information here to figure out what is actually going on. You say that req.body is returning two objects, but that they are not wrapped in an array or another object, which is fundamentally impossible.
Given the information available, my best guess is that the bodyParser is working exactly as it should, but that whatever client application you are using to send requests is sending two requests where you think it's only sending one, so when you log it you are seeing two objects and assuming they came from a single call to console.log which doesn't appear to be the case.
To confirm that, I would probably stick something like this into the bottom of the file, and then use this to log instead of using console.log directly. This will demonstrate that it's two different log entries coming from two different invocations of the route.
let counter = 0;
function logWithCounter( ...msg ) {
console.log( counter++, ...msg );
}

Categories