While writing activity it return exception
ex {"The remote server returned an error: (400) Bad Request."}
I'm using the following code :-
public static string PostRequesttoYammer(string postBody, string url,string authHeader = null, string contentType = null)
{
string results = string.Empty;
try
{
HTTPWebReq = WebRequest.CreateHttp(url);
HTTPWebReq.Method = "POST";
if (!string.IsNullOrEmpty(authHeader))
HTTPWebReq.Headers.Add("Authorization: Bearer " + authHeader);
byte[] postByte = Encoding.UTF8.GetBytes(postBody);
if (string.IsNullOrEmpty(contentType))
HTTPWebReq.ContentType = "application/x-www-form-urlencoded";
else
HTTPWebReq.ContentType = contentType;
HTTPWebReq.ContentLength = postByte.Length;
Stream postStream = HTTPWebReq.GetRequestStream();
postStream.Write(postByte, 0, postByte.Length);
postStream.Close();
HTTPWebRes = (HttpWebResponse)HTTPWebReq.GetResponse();
postStream = HTTPWebRes.GetResponseStream();
StreamReader postReader = new StreamReader(postStream);
results = postReader.ReadToEnd();
postReader.Close();
postStream.Close();
}
catch (Exception ex)
{
}
return results;
}
I have obtained access token after that i'm trying to write an activity on yammer network .enter image description here
The image shows the content of local variables of function.
check the bellow code:
yam.platform.request({
url: "activity.json",
method: "GET",
data: {
"activity": {
"actor": { "name": "name", "email": "name#domain.onmicrosoft.com" },
"action": "create",
"object": {
"url": "https://www.news.google.com",
"image": "url",
"description": "Testing Description",
"title": "Open Graph Title"
},
"private": "false",
"message": "testing commit"
}
},
success: function (activity) {
console.log("Activity request was successful.");
},
error: function (activity) {
console.error("There was an error with the request.");
}
});
Related
when my app is running is receive notification along with title message and app icon like this
but when my is killed it does not shoe message body only shows icon and title which is applications name like this
while the code for my OnMessagerecieved method is this
#Override
public void onMessageReceived(RemoteMessage message) {
String from = message.getFrom();
Map data = message.getData();
datarecieved = message;
String orderIds= "";
try {
if(data.get("accountId")!=null)
orderIds = data.get("accountId").toString();
} catch (Exception e) {
e.printStackTrace();
}
String userId=SharedPrefsUtils.getStringPreference(getApplicationContext(),"user_id");
if(userId!=null&&userId.length()>0) {
if (orderIds.equals("-101")) {
generateNotificationForOrder(getApplicationContext(), data);
} else if (!orderIds.equals("")) {
generateNotification(getApplicationContext(), data);
}
}
}
while my JSON for notification is like this
{
"to": "fcm_token",
"data": {
"type": "101 / 102 / 103",
"msg": "CustomerId",
"id": "0",
"accountId": "-101"
},
"content_available": true
}
I try to describe my asp.net Web API OAuth endpoint in swagger using Swashbuckle 5.6.0 and tried this solution:
How to show WebApi OAuth token endpoint in Swagger
My problem is, that the URL of receiving an access token and getting a new one by refresh token is the same in asp.net OAuth Authorization Server.
Adding the second URL to the Swagger Document Path fails due to the fact, that "paths" is a IDictionary<string, PathItem>.
public class AuthTokenOperation : IDocumentFilter
{
public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer)
{
// get the Token Endpoint from Config
var endpoint = Helpers.GetAppSetting("TokenEndPoint");
// Access Token
swaggerDoc.paths.Add(endpoint, new PathItem
{
post = new Operation
{
tags = new List<string> { "AccessToken" },
consumes = new string[] { "application/x-www-form-url-encoded" },
produces = new string[] { "application/json" },
parameters = new List<Parameter>
{
new Parameter
{
type = "string",
name = "username",
required = true,
#in = "formData"
},
new Parameter
{
type = "string",
name = "password",
required = true,
#in = "formData"
},
new Parameter
{
type = "string",
name = "grant_type",
required = true,
#in = "formData"
},
new Parameter
{
type = "string",
name = "client_id",
required = true,
#in = "formData"
},
new Parameter
{
type = "string",
name = "client_secret",
required = true,
#in = "formData"
}
}
}
});
// Refresh Token
swaggerDoc.paths.Add(endpoint, new PathItem
{
post = new Operation
{
tags = new List<string> { "AccessToken" },
consumes = new string[] { "application/x-www-form-url-encoded" },
produces = new string[] { "application/json" },
parameters = new List<Parameter>
{
new Parameter
{
type = "string",
name = "grant_type",
required = true,
#in = "formData"
},
new Parameter
{
type = "string",
name = "client_id",
required = true,
#in = "formData"
},
new Parameter
{
type = "string",
name = "client_secret",
required = true,
#in = "formData"
},
new Parameter
{
type = "string",
name = "refresh_token",
required = true,
#in = "formData"
}
}
}
});
}
}
Is there any possibility to describe two api methods pointing to the same endpoint, just using diffrent parameters?
Like shown here: https://api.gettyimages.com/swagger/ui/index#!/OAuth
Finally the hint "adding something meaningless" worked for our use case.
I additionally added a new model class AuthServerResponseModel, where the response of the auth request is mapped in.
public class AuthServerResponseModel
{
public string access_token { get; set; }
public string token_type { get; set; }
public int expires_in { get; set; }
public string refresh_token { get; set; }
public string audience { get; set; }
}
To make this object be known in Swagger, the class has to be added to the SchemaRegistry.
After that I could use the "#ref" tag in the response schema to declare the response type of my auth request.
public class AuthTokenOperation : IDocumentFilter
{
public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer)
{
schemaRegistry.GetOrRegister(typeof(AuthServerResponseModel));
// get the Token Endpoint from Config
string endpoint = "URL-To-The-OAuth-Endpoint";
// Access Token
swaggerDoc.paths.Add(endpoint + "#AccessToken", new PathItem
{
post = new Operation
{
operationId = "AccessToken",
tags = new List<string> { "Token" },
consumes = new string[] { "application/x-www-form-url-encoded" },
produces = new string[] { "application/json" },
parameters = new List<Parameter>
{
new Parameter
{
type = "string",
name = "username",
required = true,
#in = "formData"
},
new Parameter
{
type = "string",
name = "password",
required = true,
#in = "formData"
},
new Parameter
{
type = "string",
name = "grant_type",
required = true,
#in = "formData"
},
new Parameter
{
type = "string",
name = "client_id",
required = true,
#in = "formData"
},
new Parameter
{
type = "string",
name = "client_secret",
required = true,
#in = "formData"
},
new Parameter
{
type = "string",
name = "DeviceId",
required = false,
#in = "formData"
}
},
responses = new Dictionary<string, Response>()
{
{ "200", new Response() { description = "Ok", schema = new Schema() { type = "object", #ref = "#/definitions/AuthServerResponseModel" } } },
{ "400", new Response() { description = "BadRequest" } },
{ "404", new Response() { description = "NotFound" } }
}
}
});
// Refresh Token
swaggerDoc.paths.Add(endpoint + "#RefreshToken", new PathItem
{
post = new Operation
{
operationId = "RefreshToken",
tags = new List<string> { "Token" },
consumes = new string[] { "application/x-www-form-url-encoded" },
produces = new string[] { "application/json" },
parameters = new List<Parameter>
{
new Parameter
{
type = "string",
name = "grant_type",
required = true,
#in = "formData"
},
new Parameter
{
type = "string",
name = "client_id",
required = true,
#in = "formData"
},
new Parameter
{
type = "string",
name = "client_secret",
required = true,
#in = "formData"
},
new Parameter
{
type = "string",
name = "refresh_token",
required = true,
#in = "formData"
}
},
responses = new Dictionary<string, Response>()
{
{ "200", new Response() { description = "Ok", schema = new Schema() { type = "object", #ref = "#/definitions/AuthServerResponseModel" } } },
{ "400", new Response() { description = "BadRequest" } },
{ "404", new Response() { description = "NotFound" } }
}
}
});
}
}
Automatic Client generation using Swagger Codegen works well now.
The paths is a dictionary in swashbuckle:
public class SwaggerDocument
{
public readonly string swagger = "2.0";
public Info info;
...
public IDictionary<string, PathItem> paths;
...
}
that is why the exception "key has already been added to the collection"
On swagger we follow the Open Api Specification, and that path is a patterned field:
https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#patterned-fields
And they clearly state that duplicates is a no no for those patterned fields:
Patterned fields can have multiple occurrences as long as each has a unique name.
https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#specification
The best option is to append something meaningless (like hash) to the endpoints to make them different, it could be something like:
swaggerDoc.paths.Add(endpoint + "#Access", new PathItem ...
swaggerDoc.paths.Add(endpoint + "#Refresh", new PathItem ...
How are the guys at gettyimages getting around that?
Here are some interesting findings
Their swagger json does not have those /oauth2/token paths
you can double check directly here:
https://api.gettyimages.com/swagger/docs/3
Here is how their swagger json looks like in the latest version of the swagger-ui:
http://petstore.swagger.io/?defaultModelsExpandDepth=0&docExpansion=none&url=https://api.gettyimages.com/swagger/docs/3
The version of swagger-ui they are using at gettyimages is heavily customized, I think they are injecting additional paths using JS
https://api.gettyimages.com/swagger/ui/ext/GettyImages-Resources-OAuthGrant-js
You can do that too, it will be a lot more work than just appending something to the endpoints
I am using HttpBuilder-NG. On error I am getting following response from server.
{
"error": "JsonError",
"param": {
"obj.instructorId": [
{
"msg": "Instructor Not Found",
"args": []
}
]
}
}
But HttpBuilder is losing body. The fromServer object is coming as....
fromServer = {JavaHttpBuilder$Action$JavaFromServer#3109}
is = null
hasBody = false
headers = {Collections$UnmodifiableRandomAccessList#3113} size = 10
uri = "**********"
this$1 = {JavaHttpBuilder$Action#3092}
Code for the error handling is
config.getRequest().getHeaders().put("Authorization","Bearer " + AccessToken);
config.getRequest().getUri().setPath(path);
config.getRequest().setBody(paramValues);
config.getResponse().when(400,(fromServer, o) -> {
LazyMap lazyMap = new LazyMap();
lazyMap.put("error", fromServer.getMessage());
return lazyMap;
});
I am trying to follow the datatable example for Ajax data source (objects) found here. I am using asp.net and have the following handler which receives my data, processes it and provides the response.
public class UsersHandler : IHttpHandler
{
private const string JsHeader = #"{{""data"" {0}}}";
public void ProcessRequest(HttpContext context)
{
IEnumerable<SystemUser> data = SystemUserLogic.LoadAllSystemUsers();
List<SimpleUser> userlist = new List<SimpleUser>();
foreach (SystemUser su in data)
{
SimpleUser simple = new SimpleUser();
simple.Id = su.Id;
simple.FullName = su.NameFirst;
simple.Email = "example#email.co.uk";
userlist.Add(simple);
}
string json = JsonConvert.SerializeObject(userlist, Formatting.Indented);
context.Response.ContentType = "text/plain";
context.Response.ContentEncoding = Encoding.UTF8;
context.Response.Cache.SetNoStore();
context.Response.Expires = -1;
context.Response.Write(String.Format(JsHeader, json));
}
which deliveries the correct response when I catch it in the browser and look at the data via the network traffic. My aspx page contains the following.
$('#table_id').DataTable({
"ajax": '/Handlers_New/UsersHandler.ashx',
"columns": [
{ "data": "Id" },
{ "data": "FullName" },
{ "data": "Email" },
{ "data": "KeyResource" }
]
});
However when the page loads, I am getting this error:
DataTables warning: table id=table_id - Invalid JSON response. For more information about this error, please see http://datatables.net/tn/1
The outputted data looks like this,
{"data" [
{
"Id": 1,
"FullName": "Admin",
"Email": "example#email.co.uk",
"KeyResource": false
},
{
"Id": 2,
"FullName": "Jon",
"Email": "example#email.co.uk",
"KeyResource": false
},
{
"Id": 3,
"FullName": "Stephen",
"Email": "example#email.co.uk",
"KeyResource": false
}, etc.....
Please tell me why I am getting this error. Should I be manipulating the json object differently, or am I missing something with the Jquery datatables?
I have managed to fix my issue amazingly due to jsonlint. I ran my code through that and it turns out I was missing a ':' in my jsHeader. So what I had was:
private const string JsHeader = #"{{""data"" {0}}}";
and what I have now which now works is:
private const string JsHeader = #"{{""data"": {0}}}";
Hope this helps any one else encountering a similar issue.
I've seen this problem in many places but I can't seem to find a solution. So I have defined a Kendo grid with CRUD operations the thing is that the previous fired operations get fired again.
Say you delete entry X and then you add entry Y, the create operation fires and after that the delete operation (for X - which has been deleted) fires again. Same thing if you first create an element and then edit another, it edits the 2nd element and then it re-fires the 1st create statement and inserts a duplicate for the 1st inserted element. If you go on an on with several operations a nightmare happens with all the other previous operations being fired and sent to the controller.
My grid is:
function InitializeIPAddressesGrid(userID) {
selectedUserID = userID;
$(".ipAddresses").kendoGrid({
dataSource: IPAdressesDataSource,
sortable: {
mode: "single",
allowUnsort: false
},
remove: function (e) {
this.refresh();
var canDelete = confirm("Are you sure you want to delete this record?");
if (!canDelete) {
e.preventDefault();
}
},
height: 420,
resizable: true,
pageable: {
refresh: true,
pageSize: 10
},
selectable: "row",
toolbar: ["create"],
editable:{mode: "inline", confirmation:false} ,
columns: [{
field: "IpAddress",
title: "IP Address"
},
{
field: "Status",
title: "Status"
},
{
field: "LockedUntil",
title: "Locked until",
template: "#=kendo.toString(LockedUntil, 'yyyy/MM/dd' )#"
},
{ command: ["edit", "destroy"], title: " ", width: "180px" }
]
});
}
var IPAdressesDataSource = new kendo.data.DataSource({
type: "json",
serverPaging: true,
serverSorting: true,
serverFiltering: true,
pageSize: 10,
//scrollable:false,
transport: {
read: {
url: websiteRootUrl + '/PortalAuthorization/GetIPAddressesList',
},
update: {
url: websiteRootUrl + "/PortalAuthorization/UpdateIP",
dataType: "json",
type: 'POST',
complete: function (e) {
if (e.status != 200) {
alert(eval('(' + e.responseText + ')').Message);
}
}
},
create: {
url: websiteRootUrl + "/PortalAuthorization/CreateIP",
dataType: "json",
type: 'POST',
complete: function (e) {
if (e.status != 200) {
alert(eval('(' + e.responseText + ')').Message);
}
}
},
destroy: {
url: websiteRootUrl + "/PortalAuthorization/DeleteIP",
dataType: "json",
type: 'DELETE',
complete: function (e) {
if (e.status != 200) {
alert(eval('(' + e.responseText + ')').Message);
}
}
},
parameterMap: function (options, operation) {
if (operation == "update" && options) {
return {ipAddress: options.IpAddress ,
status: options.Status ,
lockedUntil: kendo.toString(options.LockedUntil, 'yyyy/MM/dd' ),
pkey: options.ID,
databaseID: selectedDatabaseID };
}
else
if (operation == "destroy" && options)
{
return {
databaseID: selectedDatabaseID,
pkey: options.ID,
userIDParam: selectedUserID
};
}
else
if (operation == "create" && options) {
return {ipAddress: options.IpAddress ,
status: options.Status ,
lockedUntil: kendo.toString(options.LockedUntil, 'yyyy/MM/dd' ),
pkey: options.ID,
userIDParam: selectedUserID,
databaseID: selectedDatabaseID };
}
else
{
options.databaseID = selectedDatabaseID;
options.userID = selectedUserID;
return options;
}
}
},
schema: {
model: {
id: "ID",
fields: {
IpAddress: { type: "string" },
Status: { type: "string" },
LockedUntil: { type: "date" }
}
},
data: function (data) {
return data.Items;
},
total: function (data) {
return data.TotalCount;
}
}
});
My controllers are:
public object UpdateIP(int databaseID, long pkey, string status, string lockedUntil, string ipAddress)
{
var database = [...];
DynamicDataRepository repository = [...];
string query = "...";
repository.ExecuteNonQuery(query);
return new HttpResponseMessage(HttpStatusCode.OK);
}
public object DeleteIP(int databaseID, long pkey, int? userIDParam)
{
var database = [...];
DynamicDataRepository repository = [...];
string query = "...";
repository.ExecuteNonQuery(query);
return new HttpResponseMessage(HttpStatusCode.OK);
}
public object CreateIP(int databaseID, long? pkey, string status, string lockedUntil, string ipAddress, int? userIDParam)
{
var database = [...];
DynamicDataRepository repository = [...];
string query = "...";
repository.ExecuteNonQuery(query);
return new HttpResponseMessage(HttpStatusCode.OK);
}
Do you have any ideea? where I've done something wrong? thanks in advance. P.S. the queries in the controllers work fine.
I fixed the problem, followed OnaBai's suggestion of returning the Updated/Created entity, and in the case of a Delete I returned the ID of the deleted entry.
public object UpdateIP(int databaseID, long pkey, string status, string lockedUntil, string ipAddress)
{
var database = [...];
DynamicDataRepository repository = [...];
string query = [...];
IPList updatedIP = new IPList { ID = pkey, IpAddress = ipAddress, Status = status, LockedUntil = DateTime.Today };
return Json(updatedIP, JsonRequestBehavior.AllowGet);
// return new HttpResponseMessage(HttpStatusCode.OK);
}
Only one mention: in the case of a CREATE, the method didn't seem to work so what I did is in the .complete event of the CREATE operation I did a ipGrid.dataSource.read();
ipGrid.refresh(); - so the operation doesn't repeat itself. ( I read that in this case there might be problem with the model definition - setting the ID field - but I did set that one). Many thanks to OnaBai