POST http://localhost:51348/TestService.svc/SendCredentials 400 (Bad Request) - javascript

I have been stuck at this problem for almost two days now and I don't seem to find any solution. I have hosted a WCF service on my machine that contains a method SendCredentials which accepts two string parameters.
Now I am supposed to send a public key to my service through which it will do encryption(Asymetric cryptography) and send some information back to the client.
I am not able to pass that public key to the service method from the client as it is in XML format.Here is my client side code:
$(document).ready(function () {
$("#btnSend").click(function () {
debugger;
jQuery.support.cors = true;
var doOaepPadding = true;
var rsa = new System.Security.Cryptography.RSACryptoServiceProvider();
_privateKey = rsa.ToXmlString(true);
_publicKey = rsa.ToXmlString(false);
var data = $("#txtName").val();
var name = "testvalue";
var _privateKey = rsa.ToXmlString(true);
**var _publicKey = rsa.ToXmlString(false);**
//<![CDATA[ and ]]>;
$.ajax({
type: "POST",
url: 'http://localhost:51348/TestService.svc/SendCredentials',
crossDomain: true,
data:JSON.stringify({ mac: "bac", pubKey: _publicKey }),
contentType: "application/json",
dataType: "json",
success: function (result) {
var ans = JSON.stringify(result);
alert(ans);
// result = new XMLSerializer().serializeToString(result.documentElement);
},
error: function (xhr, err) {
alert("readyState: " + xhr.readyState + "\nstatus: " + xhr.status);
alert("responseText: " + xhr.responseText);
}
});
return false;
});
});
</script>
_publicKey is the variable I want to pass but throws above said error. Any suggestions How do i pass this XML variable would be really appreciated.

I would suggest you to convert _publicKey to base64 string
convert your _publicKey to string then byte Array and use
Convert.ToBase64String(byte[] inArray)
and on the service side do the reverse
System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(endodedString), true));

Related

Google Classroom API 401 Error

I am trying to create a Google Classroom course using the Google Classroom API and a service account. I am currently experimenting using JavaScript and I have everything set up and working to get a list of course. I set up a JWT and request an authentication token which I receive.
{"access_token":"----ACCESS TOKEN HERE----------","token_type":"Bearer","expires_in":3600}
When I use this to retrieve a user's course list (via GET) there is no problem. I receive back a proper response with a list of courses which I then display in a table.
When I try to use the same process to try to create a course (via POST), I get a 401 error:
{
"error": {
"code": 401,
"message": "The request does not have valid authentication credentials.",
"status": "UNAUTHENTICATED"
}
}
This is the code I use to authenticate:
function authenticate(callback) {
function b64EncodeUnicode(str) {
str = JSON.stringify(str);
return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(match, p1) {
return String.fromCharCode('0x' + p1);
}));
}
// constuct the JWT
var jwtHeader = {
"alg":"RS256",
"typ":"JWT"
}
jwtHeader = JSON.stringify(jwtHeader);
//construct the Claim
var jwtClaim = {
"iss":"psclassroomsync#psclassroomsync.iam.gserviceaccount.com",
"scope":"https://www.googleapis.com/auth/classroom.courses https://www.googleapis.com/auth/classroom.rosters",
"sub":"myemail#address.com", //this is an admin account I shouldn't really need this but tried with and without it
"aud":"https://www.googleapis.com/oauth2/v4/token",
"exp":(Math.round(new Date().getTime()/1000) + 60 * 10),
"iat":Math.round(new Date().getTime()/1000)
}
jwtClaim = JSON.stringify(jwtClaim);
//construct the signature
var key="-----BEGIN PRIVATE KEY-----Removed-----END PRIVATE KEY-----\n";
var jwtSign = b64EncodeUnicode(jwtSign);
var sJWT = KJUR.jws.JWS.sign("RS256", jwtHeader, jwtClaim, key);
var jwt = jwtHeader + "." + jwtClaim + "." + sJWT;
//request Token
var grantType = "urn:ietf:params:oauth:grant-type:jwt-bearer";
var tokenRequest = "grant_type=" + grantType + "&assertion=" + sJWT;
var postURL = "https://www.googleapis.com/oauth2/v4/token"
request = $j.ajax({
url: postURL,
type: "post",
data: tokenRequest,
success: callback
});
}
This is the code I use to GET the course list. (this works)
$j("#getClasses").click(function(event){
function getClasses(callback){
authenticate(function(data){
console.log(JSON.stringify(data));
var access_token = data["access_token"];
var apiUrl = 'https://classroom.googleapis.com/v1/courses'
var myData = 'teacherId=~(teacheremail)&access_token='+access_token;
var files = $j.ajax({
url: apiUrl,
type: "get",
data: myData,
success: function (data) {
var retreivedClasses = JSON.stringify(data);
for(var i = 0; i < data['courses'].length; i++){
nextObject = data['courses'];
$j('#classListTable').append('<tr><td>' + nextObject[i]['name'] + '</td><td>' + nextObject[i]['courseState'] + '</td><td>' + nextObject[i]['enrollmentCode'] + '</td></tr>');
}
//$j('#classList').text(retreivedClasses);
}
});
});
}
getClasses();
});
This is the code that I use to create a course via POST. I've hard coded a few of the variables for testing but still gives the 401 error.
$j("#createClass").click(function(event){
function createClass(callback){
authenticate(function(data){
console.log(JSON.stringify(data));
var access_token = data["access_token"];
var tokenInfo = $j.ajax({
url: 'https://www.googleapis.com/oauth2/v3/tokeninfo',
type: 'get',
data: "access_token="+access_token
});
var apiUrl = 'https://classroom.googleapis.com/v1/courses'
var myData = 'access_token='+access_token + '&ownerId=myemail#address.com&name=myClass'
console.log(myData);
var newGoogleClassroom = $j.ajax({
url: apiUrl,
type: "post",
data: myData,
success: function (data) {
var apiResponse = JSON.stringify(data);
$j('#classCreated').text(apiResponse);
}
});
});
};
createClass();
});
Finally, this is what I get when I get the token info. It looks fine to me i.e. proper scopes: (but I am new at this)
{
"azp": "removed",
"aud": "removed",
"scope": "https://www.googleapis.com/auth/classroom.courses https://www.googleapis.com/auth/classroom
.rosters",
"exp": "1474512198",
"expires_in": "3600",
"access_type": "offline"
}
I'd be grateful for any help.
Doug
P.S. I get the security implications of this code. It is in a secure environment for experimentation only. It won't see the light of day.
Based from this forum which is also receiving a 401 error, try to revoke the old oauth. As stated in this related thread, the 401 Unauthorized error you experienced may be related to OAuth 2.0 Authorization using the OAuth 2.0 client ID.
Suggested action: Refresh the access token using the long-lived refresh token. If this fails, direct through the OAuth flow.

How do I download a file that is returned by the server in an Ajax call?

I have a download function where the idea is that when the user clicks a button, it does an ajax call to a function that will create a csv file containing all of the information the user was viewing, and will return the file as a download. I have the server function creating a csv file, but I'm not sure how to make it download. This is my server-side code:
public ActionResult Download(Guid customerOrderId)
{
var order = this.UnitOfWork.GetRepository<CustomerOrder>().Get(customerOrderId);
var csv = new StringBuilder();
csv.Append("Customer,Bill To Name,Ship To Name,Patient,Order#,Order Date," +
"Line,Item#,Item Description,Qty,UOM,Price,Ext Price,Carrier," +
"Notes,Purchase Order");
var customer = order.CustomerNumber;
var billToName = order.BTDisplayName;
var shipToName = order.ShipTo.CustomerName;
var orderNum = order.OrderNumber;
var orderDate = order.OrderDate;
var carrier = order.ShippingDisplay;
var notes = order.Notes;
var subtotal = order.OrderSubTotalDisplay;
var total = order.OrderGrandTotalDisplay;
var shipping = order.ShippingAndHandling;
var tax = order.TotalSalesTaxDisplay;
var patient = "";
var purchaseOrder = order.CustomerPO;
foreach (var cartLine in order.OrderLines)
{
var line = cartLine.Line;
var itemNum = cartLine.Product.ProductCode;
var itemDesc = cartLine.Description;
var qty = cartLine.QtyOrdered;
var uom = cartLine.UnitOfMeasure;
var price = cartLine.ActualPriceDisplay;
var ext = cartLine.ExtendedActualPriceDisplay;
//Customer,Bill To Name,Ship To Name,Patient,Order#,Order Date," +
//"Line,Item#,Item Description,Qty,UOM,Price,Ext Price,Carrier," +
//"Notes,Purchase Order
var newLine = string.Format("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12},{13},{14},{15}",
customer, billToName, shipToName, patient, orderNum, orderDate, line, itemNum, itemDesc,
qty, uom, price, ext, carrier, notes, purchaseOrder);
csv.AppendLine(newLine);
}
csv.AppendLine();
csv.AppendLine("Subtotal,Shipping & Handling,Tax,Total");
csv.AppendLine(string.Format("{0},{1},{2},{3}", subtotal, shipping, tax, total));
var filename = "MSD-Order-" + orderNum + ".csv";
var bytes = Encoding.UTF8.GetBytes(csv.ToString());
return this.File(bytes, "text/csv");
}
And here is the ajax method:
function download(customerOrderId) {
$.ajax({
url: insite.core.actionPrefix + '/Checkout/Download/?customerOrderId=' + customerOrderId,
type: 'Post',
contentType: "application/json; charset=utf-8",
async: false,
cache: false,
success: function (data) {
alert("downloaded");
},
error: function (ex) {
console.log(ex);
}
});
}
In the success of the ajax call, I checked the value of "data" and it has the information, but I'm not sure how to make it download. What do I do once I receive the data?
Can't you just download it via a href like this?
public FileContentResult Download(Guid customerOrderId)
{
// your code
var response = new FileContentResult(bytes, "text/csv");
response.FileDownloadName = filename;
return response;
}
The link:
Download
You can store the file on server and send the URL with response. Then on ajax success function window.location=data.URL
Venerik has a valid answer as well, but keeping in line with your current implementation, I'd suggest the following.
You can return the string of the URL after saving the file to your server. Then do the window location redirection upon your success. I removed the variable assignments since nothing is being done with them other than sending to a method.
Here we write the file and return the string. You'll need to adjust the return to match your site information, etc.
public ActionResult Download(Guid customerOrderId)
{
var order = this.UnitOfWork.GetRepository<CustomerOrder>().Get(customerOrderId);
var csv = new StringBuilder();
csv.AppendLine("Customer,Bill To Name,Ship To Name,Patient,Order#,Order Date," +
"Line,Item#,Item Description,Qty,UOM,Price,Ext Price,Carrier," +
"Notes,Purchase Order");
foreach (var cartLine in order.OrderLines)
{
//Customer,Bill To Name,Ship To Name,Patient,Order#,Order Date," +
//"Line,Item#,Item Description,Qty,UOM,Price,Ext Price,Carrier," +
//"Notes,Purchase Order
csv.AppendLine(string.Format("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12},{13},{14},{15}",
order.CustomerNumber, order.BTDisplayName, order.ShipTo.CustomerName, "", order.OrderNumber, order.OrderDate, cartLine.Line, cartLine.Product.ProductCode, cartLine.Description,
cartLine.QtyOrdered, cartLine.UnitOfMeasure, cartLine.ActualPriceDisplay, cartLine.ExtendedActualPriceDisplay, order.ShippingDisplay, order.Notes, order.CustomerPO));
}
csv.AppendLine();
csv.AppendLine("Subtotal,Shipping & Handling,Tax,Total");
csv.AppendLine(string.Format("{0},{1},{2},{3}", order.OrderSubTotalDisplay, order.ShippingAndHandling, order.TotalSalesTaxDisplay, order.OrderGrandTotalDisplay));
var filename = "MSD-Order-" + orderNum + ".csv";
using (StreamWriter sw = File.CreateText(Server.MapPath("~/files/" + filename))
{
sw.Write(csv.ToString());
}
// adjust your url accordingly to match the directory to which you saved
// '/files/' corresponds to where you did the File.CreateText
// returning Content in an ActionResult defaults to text
return Content("http://foo.com/files/" + filename);
}
And in your AJAX method update your success function to redirect the page which will prompt the download:
function download(customerOrderId) {
$.ajax({
url: insite.core.actionPrefix + '/Checkout/Download/?customerOrderId=' + customerOrderId,
type: 'Post',
contentType: "application/json; charset=utf-8",
async: false,
cache: false,
success: function (data) {
window.location.href = data;
},
error: function (ex) {
console.log(ex);
}
});
}

What is the right way to use "context:..." in an AJAX call?

So I'm aware that there are a big amount of threads about AJAX and the use of the context but after hours of reading and trying I open a new Thread.
So I have this (shorten version) javascript function:
this.CallService = function () {
var Type = this.Type;
var Url = this.Url;
var Data = this.Data;
var ContentType = this.ContentType;
var DataType = this.DataType;
var ProcessData = this.ProcessData;
var ClipUrl = this.ClipUrl;
var CountMax = this.CountMax;
var Callback = this.Callback;
var SucceededServiceCallback = this.SucceededServiceCallback;
var FailedServiceCallback = this.FailedServiceCallback;
return $.ajax({
type: Type, //GET or POST or PUT or DELETE verb
url: Url, // Location of the service
data: Data, //Data sent to server
contentType: ContentType, // content type sent to server
dataType: DataType, //Expected data format from server
processdata: ProcessData, //True or False
context: this,
}).done(function (msg) {//On Successfull service call
SucceededServiceCallback(this, msg);
}).fail(function (msg) {
FailedServiceCallback(this, msg);
});
}
The Important part here are the context: this and the two callbacks done and fail. Im those two callbacks I give the this context to my callback functions:
this.SucceededServiceCallback = function (context, result) {
if (null != context) {
UpdateDebugInfo(context, "succeeded: " + context.DataType + " URL: " + context.Url + " Data: " + context.Data + " Result: " +result);
}
if (context != null && context.DataType == "json" && result != null && context.Callback != null) {
context.Callback(context, result);
}
}
Here the important part is that I use the context to see access the variables DataType, Callback, Url etc.
The Problem now is that the context is set to the last context used (it's an asynchron call so all the variable are the variable from the last call). So I'm pretty sure something is wrong with that context: this, part. I just don't know how to use this right. Thanks for your help.
tl;dr:
I use context: this in an Ajax call. Context is always set to the last "this" called. I want to use the "this" of the call.
You are "caching" all your variables before you fire each request, but in your SucceededServiceCallback function you are inspecting this.XXX - which is not the var Type it looks like you are expecting, but the actual this.Type itself.
What you could do is put these properties into an object and pass it as context, rather than your main object:
this.CallService = function () {
var context = {
Type : this.Type,
Url : this.Url,
Data : this.Data,
ContentType : this.ContentType,
DataType : this.DataType,
ProcessData : this.ProcessData,
ClipUrl : this.ClipUrl,
CountMax : this.CountMax,
Callback : this.Callback
};
var SucceededServiceCallback = this.SucceededServiceCallback;
var FailedServiceCallback = this.FailedServiceCallback;
return $.ajax({
type: Type, //GET or POST or PUT or DELETE verb
url: Url, // Location of the service
data: Data, //Data sent to server
contentType: ContentType, // content type sent to server
dataType: DataType, //Expected data format from server
processdata: ProcessData, //True or False
context: context,
}).done(function (msg) {//On Successfull service call
SucceededServiceCallback(this, msg);
}).fail(function (msg) {
FailedServiceCallback(this, msg);
});
}

Returning an object from Web Service to Ajax Request success callback function

Hello Fellow Developers,
I have a SSN textbox that onblur calls a function which does an ajax request to a Web Method to decide if an employee has been previously hired.
The Web Method returns a TermedEmployee Object to the success callback, but I'm unsure how to parse the object.
$('#<%=FormView1.FindControl("SSNField").ClientID%>').blur(hideValue);
hideValue = function (ev) {
var $this = $(this);
$this.data('value', $this.val());
$('#<%=FormView1.FindControl("hiddenSSN").ClientID%>').val($this.val());
var data2Send = '{"SSN": ' + $this.val() + ' }';
$.ajax({
type: "POST",
url: "AuthforHire.aspx/EmployeeisRehire",
data: data2Send,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (result) {
var obj = JSON.stringify(result.d);
if (obj.IsTermed) {
$('#%=RadWindowRehire.ContentContainer.FindControl("TextBoxTermID").ClientID%>').val(arg.d);
var wndWidth = 900;
var wndHeight = 500;
var wnd = window.radopen(null, "RadWindowRehire");
}
},
error: function (xhr) {
alert('Form update failed. '); //error occurred
}
});
Below is a minified version of my webMethod, which works correctly
[System.Web.Services.WebMethod]
public static TermedEmployee EmployeeisRehire(string SSN)
{
TermedEmployee termedEmp = new TermedEmployee();
// Db call to get necessary data.
termedEmp.Name = dr["name"];
termedEmp.TermDate = Convert.ToDateTime(dr["TermDate"].ToString());
......
}
So How Can I extract Name, TermDate,StartDate, ReasonforTerm, etc from the object returned to the callback function?
Thank you in advance!
The first line in your success callback is:
var obj = JSON.stringify(result.d);
Which is trying to serialize what ASP.Net will already have serialized for you.
Change this to:
var obj = result.d;
And you will then have access to obj.Name, obj.TermDate and all the other properties by name.

How to pass json data via ajax?

I am working a visual studio 2012 MVC program.
I use ajax to send data to a controller and wish the controller returns a body of html. the data is in json format. the data is a string name and decimal TotFees.
I found that the parameters value in the public ActionResult ImmPay(string Name) in the controller are always null. Finally I tried just to pass name, but the value of name in the controller side is still null.
what is wrong in my code, and how to solve the problem? Thank you.
View:
function ImmPay()
{
var name = "ASP";
var TotFees = 100.01;
//var dd = "{\'name\':\'" + name + "\', \'TotFees\':\'" + TotFees + "\'}";
//var dd = "{\'name\':\'" + name + "\', \'TotFees\':\'" + TotFees + "m\'}";
dd = "{\'b\':\'" + b + "\'}";
dd = JSON.stringify(dd);
$.ajax({
url: '#Url.Action("ImmPay", "Consult")',
type: 'GET',
async: true,
data: dd,
contentType: 'application/json',
context: document.body,
success: function (response, textStatus, jqXHR) {
$("#dialog-immpay").html(response);
$("#dialog-immpay").dialog("open");
},
error: function (jqXHR, textStatus, errorThrown) {
alert(textStatus);
},
complete: function () {
;
}
});
}
Controller:
public ActionResult ImmPay(string Name)
{
do something here
}
JSON.stringify takes an object or an array and converts it into JSON, so you can build your data into an object and stringify it like so
dd = JSON.stringify({b: b});

Categories