Delete object in bucket, C# ASP.NET - c#

I'm trying to delete an object from a bucket. Reading the docs it all sounds super simple, but I just can't seem to get it working. On the server side I have the following in ASP.NET:
[HttpDelete]
[Route("api/forge/oss/objects/delete")]
public async Task<dynamic> DeleteObject_fromBucket()
{
// basic input validation
HttpRequest req = HttpContext.Current.Request;
if (string.IsNullOrWhiteSpace(req.Params["bucketKey"]))
throw new System.Exception("BucketKey parameter was not provided.");
if (string.IsNullOrWhiteSpace(req.Params["objectName"]))
throw new System.Exception("ObjectName parameter was not provided.");
string bucketKey = req.Params["bucketKey"];
string objectName = req.Params["objectName"];
// call API to delete object on the bucket
dynamic oauth = await OAuthController.GetInternalAsync();
ObjectsApi objects = new ObjectsApi();
string access_token = oauth.access_token; ;
objects.Configuration.AccessToken = access_token;
// delete the file/object
await objects.DeleteObjectAsync(bucketKey, objectName);
return 0;
}
The client side:
function deleteObject(node) {
result = window.confirm('Wollen Sie dieses Modell löschen');
if (result == false) { return; }
else {
var bucketKey = node.parents[0];
var objectName = node.text;
var formData = new FormData();
formData.append('bucketKey', bucketKey);
formData.append('objectName', objectName);
$.ajax({
url: 'api/forge/oss/objects/delete',
data: formData,
contentType: false,
processData: false,
type: 'DELETE', // man könnte auch method: schreiben
success: function (data) {
$('#appBuckets').jstree(true).refresh_node(node);
}
});
}
}
I always get the exception that it fails to make API call. The bucketKey and objectName are both Strings. Could anyone help me understand where I'm going wrong?
Thanks a lot.

I happened to make a working code for one attendee in Sydney Accelerator this week. The code snippet is tested on Learn Forge Tutorial (2 legged workflow). One is deleting bucket, the other is deleting object. It looks you are also testing with that skeleton of tutorial?
I made a similar code like yours at the beginning, but my VS threw error when compiling. Finally, I found it is due to the return value. Since it is a HTTP Request, it looks 0 does not make sense to a response. In addition, the default scope of the internal token in that tutorial does not contain bucket delete and data write (for deleting object). I got the detail error with the response of client side.
After adding those scopes at OAuthController.cs. All started to work:
public static async Task<dynamic> GetInternalAsync()
{
if (InternalToken == null || InternalToken.ExpiresAt <
DateTime.UtcNow)
{
InternalToken = await Get2LeggedTokenAsync(new Scope[] {
Scope.BucketCreate, Scope.BucketRead, Scope.DataRead,
Scope.DataCreate,Scope.BucketDelete,Scope.DataWrite});
InternalToken.ExpiresAt =
DateTime.UtcNow.AddSeconds(InternalToken.expires_in);
}
return InternalToken;
}
If these are not helpful for your case, I'd suggest building the Forge SDK source project, adding to your project, and debugging the corresponding methods to see what the exact error is. Please feel free to let us know if you have any questions on this.
Server Side:
[HttpPost]
[Route("api/forge/oss/buckets/delete")]
public async Task<dynamic> DeleteBucket([FromBody]CreateBucketModel bucket)
{
BucketsApi buckets = new BucketsApi();
dynamic token = await OAuthController.GetInternalAsync();
buckets.Configuration.AccessToken = token.access_token;
await buckets.DeleteBucketAsync(bucket.bucketKey);
//or
//buckets.DeleteBucket(bucket.bucketKey);
return Task.CompletedTask;
}
[HttpPost]
[Route("api/forge/oss/objects/delete")]
public async Task<dynamic> DeleteObject([FromBody]DeleteObjectModel
objInfo)
{
ObjectsApi objs = new ObjectsApi();
dynamic token = await OAuthController.GetInternalAsync();
objs.Configuration.AccessToken = token.access_token;
await objs.DeleteObjectAsync(objInfo.bucketKey, objInfo.objectKey);
//or
//objs.DeleteObject(objInfo.bucketKey, objInfo.objectKey);
return Task.CompletedTask;
}
public class CreateBucketModel
{
public string bucketKey { get; set; }
}
public class DeleteObjectModel
{
public string bucketKey { get; set; }
public string objectKey { get; set; }
}
Client Side:
function deleteBucket() {
//select one bucket node of the tree
var bucketKey = $('#appBuckets').jstree(true).get_selected(true)[0].id;
var policyKey = $('#newBucketPolicyKey').val();
jQuery.post({
url: '/api/forge/oss/buckets/delete',
contentType: 'application/json',
data: JSON.stringify({ 'bucketKey': bucketKey,
'policyKey': policyKey }),
success: function (res) {
$('#appBuckets').jstree(true).refresh();
alert('Bucket deleted')
},
error: function (err) {
alert('Bucket not deleted')
console.log(err);
}
});
}
function deleteObject() {
//assume the first selected tree node is bucket
var bucketKey = $('#appBuckets').jstree(true).get_selected(true)[0].text;
//assume the second selected tree node is object
var objectKey = $('#appBuckets').jstree(true).get_selected(true)[1].text;
jQuery.post({
url: '/api/forge/oss/objects/delete',
contentType: 'application/json',
data: JSON.stringify({ 'bucketKey': bucketKey,
'objectKey': objectKey }),
success: function (res) {
$('#appBuckets').jstree(true).refresh();
alert('Object deleted')
},
error: function (err) {
alert('Object not deleted')
console.log(err);
}
});
}

URL should be
url: '/api/forge/oss/objects/delete'
instead of url: 'api/forge/oss/objects/delete'

Related

Ajax method calling a Web Api who its consuming a gRPC Service (how to get a list from a db?): Errors 415 and 400

I have problems in my web console, first it gives me error 415 without contentType: 'application/json; charset=UTF-8', in ajax method and with it gives me error 400.
I also try doing debug if the error is in backend code but it never happens and it jumps off (this don't make any sense, the debugger should run...)
My goal is to return a list of users and their email, something like this
//trying to do this in my service
IEnumerable()
//class c#
ShowUsers:
(string)Username: User1
(string)Email:user1#example.com
But I'm doing this in gRPC, so I'll have a web API controller calling the gRPC method
As there is no IEnumerable in gRPC, so my proto and method look like this:
Proto:
syntax = "proto3";
option csharp_namespace = "GrpcService1.Protos";
package UserAuth;
service UserAuth {
rpc GetAllUsers(MessageRequest) returns(ListUsersResponse);
}
message ListUserResponse{
string username = 1;
string email = 2;
}
message ListUsersResponse{
repeated ListUserResponse lstUsers = 1;
}
message MessageRequest{
string message = 1;
}
gRPC method service c#
public override Task<ListUsersResponse> GetAllUsers(MessageRequest request, ServerCallContext context)
{
//This gives me an IEnumerable<ShowUsers> (this is
correct)
var a = _userBll.getAllUsers();
//Here in this lines maybe be the problem but I don't
//know where (maybe be because of json type or something into a list)
//here im trying to put separate list of users and emails
var names = a.Select(x => x.Username);
var emails = a.Select(y => y.Email);
//here im trying to put the lists into a Response
var all = new ListUserResponse
{
Username = names.ToString(),
Email = emails.ToString()
};
//the above will give the same but the
ListUsersResponse is a repeated attribute
var response = new ListUsersResponse
{
LstUsers = { all }
};
//all ok
request.Message = "Sucess";
return Task.FromResult(response);
}
The code below is correct (I test with a POST method the controller and the ajax I test without the gRPC and works fine) but you will have the idea of ​​what I'm doing (its the controller and the ajax method)
Controller [HTTPGET]:
[HttpGet("getAllUserInfo_2"), Authorize]
public async Task<ActionResult<ListUsersResponse>> GetAll_2([FromBody] MessageRequest message)
{
_logger.Log(LogLevel.Information, "Request Received for AuthController::Register");
var results = await _userClient.GetAllUsersAsync(message);
_logger.Log(LogLevel.Information, "Sending Response from AuthController::Register");
return Ok(results);
}
Ajax Method:
$(function b() {
debugger;
var $users_A = $('#users_A');
$.ajax({
contentType: 'application/json; charset=UTF-8', //if I comment this gives me 415
url: uri_3_2,
type: 'GET',
dataType: 'json',
beforeSend: function(request) {
request.setRequestHeader("Authorization", 'Bearer ' + localStorage.getItem("key"));
},
success: function(date) {
$.each(data, function (i, rice) {
$users_A.append('<li>Name: ' + arroz.username + ' Email: ' + arroz.email + ' </li>');
});
},
error: function (xhr, textStatus, errorThrown) {
console.log('XHR:' + xhr + '\nTextStatus:' + textStatus + '\nErrorThrown:' + errorThrown); //this should give me more info about the error but don't works... But it
//works fine the implementation code
$users_A.append('<h4>ERRRROORRRR</h4>');
}
});
});
Any help is welcome
A bi-directional streaming RPC would be a better option as it will
improve your performance significantly and may solve your problem.
you need to change your proto as the following:
syntax = "proto3";
option csharp_namespace = "GrpcService1.Protos";
package UserAuth;
service UserAuth {
rpc GetAllUsers(MessageRequest) returns(stream UserResponse);
}
message UserResponse{
string username = 1;
string email = 2;
}
message MessageRequest{
string message = 1;
}
gRPC method service c#
public override async Task GetAllUsers(MessageRequest request, IServerStreamWriter<UserResponse> responseStream, ServerCallContext context)
{
var users = _userBll.getAllUsers();
foreach (user in users)
{
await responseStream.WriteAsync(new UserResponse
{
Username = user.Username.ToString(),
Email = user.Email.ToString()
});
}
}
in client:
public async Task<List<UserResponse> GetAllUsers()
{
var userResponseList = new List<UserResponse>();
using var call = client.GetAllUsers(new MessageRequest());
while (await call.ResponseStream.MoveNext())
{
var userResponse = new UserResponse
{
Username = call.ResponseStream.Current.Username,
Email = call.ResponseStream.Current.Email
});
userResponseList.Add(userResponse);
}
return userResponseList;
}
the client object has come from the channel which is created from the gRPC service URL (I assume you know it).
Now you can make this a service and call it by dependency injection from your controller.
I didn't test it so it may have some compile errors but the approach is correct.

WebAPI - HTTP405: BAD METHOD - The HTTP verb used is not supported using JavaScript

I'm posting to my Web API on Azure from a remote webpage. I use the following:
$.ajax({
type: "POST",
url: BaseHref + "/api/PIRknownPersons/",
data: data,
contentType: "application/json; charset=UTF-8",
success: function (response) {
//alert('Saved known ');
},
error: function (e) {
//alert('Unable to save Known ' );
}
});
I could be wrong but it looks like remote posting is blocked on Azure as the code works fine when I do it locally. Is this the case? Is there a setting on Azure that I can turn off?
PIRknownPersons -
namespace TripWeb.Controllers
{
public class PIRknownPersonsController : ApiController
{
private TripDB3Entities db = new TripDB3Entities();
// POST: api/PIRknownPersons
[ResponseType(typeof(bool))]
public HttpResponseMessage Post([FromBody]ApiPIRknownPerson APIPIRknownPerson)
{
var inst = db.Institutions.Where(x => x.RemoteID == APIPIRknownPerson.RemoteID).FirstOrDefault();
if (inst == null)
{
return Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "Action Not Authorized");
}
var newPIRknownPerson = ObjectMapper.GetEfApiPIRknownPerson(APIPIRknownPerson);
try
{
db.PIRknownPersons.Add(newPIRknownPerson);
db.SaveChanges();
return Request.CreateResponse<bool>(HttpStatusCode.OK, true);
}
catch (Exception ex)
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex.Message);
}
}
}
}
I found the problem - or at least I got it working. I did two things:
Enabled CORS on Azure through the control panel
Appended [System.Web.Http.AcceptVerbs("GET", "POST")] to the top of my controller files.
Don't know if both are needed but it works now anyway.

Image Uploading using angular and asp.net

am trying to get the image from the PC and upload it into the DB
as like "/Images/aaa.jpg" am new to angular. Here am tried one example. Its not worked For me. i have stucked almost 3 days to solve this. but i couldn't found any tutorials for my requirement. when i debug the id, and descriptions are passing correctly, but For the path its remaining always null. and i know i need to set path to where the picture will save. but i dont know how to do that, please can anyone help me to solve this issue.
I tried this one to upload image.
$scope.uploadFile = function(files) {
var fd = new FormData();
//Take the first selected file
fd.append("file", files[0]);
$http.post(uploadUrl, fd, {
withCredentials: true,
headers: {'Content-Type': undefined },
transformRequest: angular.identity
}).success(ya).error( noo );
};
There is a add button if user hit add button details want to be save. for this i used this one.
$scope.AddImage = function () {
var dataObj = {
Id: $scope.Id,
Description: $scope.Description,
Path: $scope.Path,
Location: $scope.Location,
};.
var request = $http({
method: 'POST',
url: urls.api + 'Images/AddImage',
//data: JSON.stringify(dataObj)
data: dataObj
}).success(function (data, status) {
alert('saved succesfully');
})
.error(function (error) {
$scope.status = 'Unable to load ImageDetails : ' + error.message;
console.log($scope.status);
});
}
this is my asp.net services.
public async Task<int?> Addimg (Addimg dto)
{
try
{
var d = _dbContext.img
.FirstOrDefault();
d.img_Path = dto.Path.ToString();
d.img_Description = dto.Description;
d.img_Location = dto.Location;
//mark entry as modifed
_dbContext.Entry(d).State = EntityState.Modified;
await _dbContext.SaveChangesAsync();
return d.img_Id;
}
this my asp.net controller
[HttpPost]
[Route("AddImage")]
public async Task<IHttpActionResult> AddBanner(DisplayBannersDto dto)
{
if (!ModelState.IsValid)
return BadRequest(ModelState);
int? result = await _service.Addbanner(dto);
return Ok();
}
}
Please provide if there is any alternative codes.
It looks like you're uploading a file and doing nothing with it...
You could add something like the following property to your DisplayBannersDto model:
public Stream InputStream { get; set; }
You can then either save the file to disk from the stream, or in the database as a blob.

WebApi Routing to Action with Object Parameter [duplicate]

I don´t know why my parameter "ParametroFiltro Filtro" is getting null, the other parameters "page" and "pageSize" is getting OK.
public class ParametroFiltro
{
public string Codigo { get; set; }
public string Descricao { get; set; }
}
My ApiController Get method:
public PagedDataModel<ParametroDTO> Get(ParametroFiltro Filtro, int page, int pageSize)
My ajax call:
var fullUrl = "/api/" + self.Api;
$.ajax({
url: fullUrl,
type: 'GET',
dataType: 'json',
data: { Filtro: { Codigo: '_1', Descricao: 'TESTE' }, page: 1, pageSize: 10 },
success: function (result) {
alert(result.Data.length);
self.Parametros(result.Data);
}
});
You are trying to send a complex object with GET method. The reason this is failing is that GET method can't have a body and all the values are being encoded into the URL. You can make this work by using [FromUri], but first you need to change your client side code:
$.ajax({
url: fullUrl,
type: 'GET',
dataType: 'json',
data: { Codigo: '_1', Descricao: 'TESTE', page: 1, pageSize: 10 },
success: function (result) {
alert(result.Data.length);
self.Parametros(result.Data);
}
});
This way [FromUri] will be able to pick up your complex object properties directly from the URL if you change your action method like this:
public PagedDataModel<ParametroDTO> Get([FromUri]ParametroFiltro Filtro, int page, int pageSize)
Your previous approach would rather work with POST method which can have a body (but you would still need to use JSON.stringify() to format body as JSON).
Provide the contentType property when you make the ajax call. Use JSON.stringify method to build the JSON data to post. change the type to POST and MVC Model binding will bind the posted data to your class object.
var filter = { "Filtro": { "Codigo": "_1", "Descricao": "TESTE" },
"page": "1", "pageSize": "10" };
$.ajax({
url: fullUrl,
type: 'POST',
dataType: 'json',
contentType: 'application/json',
data: JSON.stringify(filter),
success: function (result) {
alert(result.Data.length);
self.Parametros(result.Data);
}
});
It's also possible to access POST variables via a Newtonsoft.Json.Linq JObject.
For example, this POST:
$.ajax({
type: 'POST',
url: 'URL',
data: { 'Note': note, 'Story': story },
dataType: 'text',
success: function (data) { }
});
Can be accessed in an APIController like so:
public void Update([FromBody]JObject data)
{
var Note = (String)data["Note"];
var Story = (String)data["Story"];
}
If you append json data to query string, and parse it later in web api side. you can parse complex object too. It's useful rather than post json object, espeicaly in some special httpget requirement case.
//javascript file
var data = { UserID: "10", UserName: "Long", AppInstanceID: "100", ProcessGUID: "BF1CC2EB-D9BD-45FD-BF87-939DD8FF9071" };
var request = JSON.stringify(data);
request = encodeURIComponent(request);
doAjaxGet("/ProductWebApi/api/Workflow/StartProcess?data=", request, function (result) {
window.console.log(result);
});
//webapi file:
[HttpGet]
public ResponseResult StartProcess()
{
dynamic queryJson = ParseHttpGetJson(Request.RequestUri.Query);
int appInstanceID = int.Parse(queryJson.AppInstanceID.Value);
Guid processGUID = Guid.Parse(queryJson.ProcessGUID.Value);
int userID = int.Parse(queryJson.UserID.Value);
string userName = queryJson.UserName.Value;
}
//utility function:
public static dynamic ParseHttpGetJson(string query)
{
if (!string.IsNullOrEmpty(query))
{
try
{
var json = query.Substring(7, query.Length - 7); //seperate ?data= characters
json = System.Web.HttpUtility.UrlDecode(json);
dynamic queryJson = JsonConvert.DeserializeObject<dynamic>(json);
return queryJson;
}
catch (System.Exception e)
{
throw new ApplicationException("can't deserialize object as wrong string content!", e);
}
}
else
{
return null;
}
}
In .NET Core, the HttpClient sets the transfer-encoding: chunked header by default. This can cause the .NET Web API controller parameters to be null.
To get around this, you'll need to set the ContentLength header explicitly:
var json = JsonConvert.SerializeObject(myObject);
var content = new StringContent(json, Encoding.UTF8, "application/json");
content.Headers.ContentLength = json.Length;
var response = await client.PostAsync("http://my-api.com", content);
SO answer if you already know the transfer-encoding header is the issue: How to disable Chunked Transfer Encoding in ASP.Net C# using HttpClient
Related bug which won't be fixed, which gives some insight into the problem: https://github.com/dotnet/runtime/issues/30283

Getting JSON Object from MVC Controller

What I want is to protect my developer key while making an Ajax call to a cross-domain. Before I would just go straight to the url and plug in my key. Like this
$.ajax({
url: "https://na.api.pvp.net/api/lol/na/v2.3/team/TEAM-ID?api_key=mykey",
type: "GET",
data: {},
success: function (json) {
console.log(json);
console.log(json[teamID].name);
console.log(json[teamID].fullId);
console.log(json[teamID].roster.ownerId);
console.log(json[teamID].tag);
},
error: function (error) {}
});
This would give me the following Object, which I could easily parse out.
However, as mentioned, any person could easily grab my key during this process. So I decided to move this action to my Controller (yes I know there shouldn't be business logic here, but it is more secure and this is a quick process).
So what I am doing now is running my Javascript, which calls the Controller for a Json return.
Javascript
$.ajax({
url: "/Competitive/teamLookUp",
type: "POST",
data: "ID=" + teamID,
success: function (json) {
console.log(json);
},
error: function(error) {
}
});
And my Controller takes that in and attempts to return the JSON.
[HttpPost]
public ActionResult teamLookUp(string ID)
{
HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create("https://na.api.pvp.net/api/lol/na/v2.3/team/" + ID + "?api_key=myKey");
myReq.ContentType = "application/json";
var response = (HttpWebResponse)myReq.GetResponse();
string text;
using (var sr = new StreamReader(response.GetResponseStream()))
{
text = sr.ReadToEnd();
}
return Json(new { json = text });
}
However during this processs I return a string that is not a JSON object, thus cannot be parsed by my script.
It returns the entire json as one long string.
At this point I tried to add the following to my Controller.
var json2 = JsonConvert.DeserializeObject(text);
return Json(new { json = json2 });
But all that returned was some empty Object.
I have been trial and error'ing, searching, and guessing for the past 4 hours. I have no idea what to try anymore. I just want my Controller to pass back an Object that can be readable again like this. (Or at least some sort of formatted json object)
$.ajax({
url: "/Competitive/teamLookUp",
type: "POST",
data: "ID=" + teamID,
success: function (json) {
console.log(json);
console.log(json[teamID].name);
console.log(json[teamID].fullId);
console.log(json[teamID].roster.ownerId);
console.log(json[teamID].tag);
},
error: function (error) {}
});
Your method doesn't appear to need to be a POST as it is just getting data rather than modifying it. Therefore you could set it to be a GET instead.
Example
[HttpGet]
public JsonResult teamLookUp(string ID)
{
// Your code
return Json(text, JsonRequestBehavior.AllowGet);
}
Here's an excerpt from your code:
[HttpPost]
public ActionResult teamLookUp(string ID)
{
HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create("https://na.api.pvp.net/api/lol/na/v2.3/team/" + ID + "?api_key=myKey");
myReq.ContentType = "application/json";
// here's how to set response content type:
Response.ContentType = "application/json"; // that's all
var response = (HttpWebResponse)myReq.GetResponse();
string text;
using (var sr = new StreamReader(response.GetResponseStream()))
{
text = sr.ReadToEnd();
}
return Json(new { json = text }); // HERE'S THE ERRING LINE
}
Based on the response you received, I could understand that text already contains you desired JSON.
Now replace return Json(new { json = text }); with Json(text); and that should fix it.
To answer your question in the comments, here's how you can read the response data:
$.ajax({
url: "/Competitive/teamLookUp",
type: "POST",
data: "ID=" + teamID,
dataType: "json", // type of data you're expecting from response
success: function (json) {
console.log(json);
console.log(json[teamID].name);
console.log(json[teamID].fullId);
console.log(json[teamID].roster.ownerId);
console.log(json[teamID].tag);
},
error: function (error) {}
});
I think the problem lies where you say return Json(new {json = text;}). That's telling the json serializer to dump all your data into a property in the json obect called 'json', which is what you're seeing in the response.
Try return Json(text) instead.
Ending up using WebClient
[HttpPost]
public ActionResult teamLookUp(string ID)
{
string text = "";
try
{
using (var webClient = new System.Net.WebClient())
{
webClient.Encoding = Encoding.UTF8;
var json2 = webClient.DownloadString("https://na.api.pvp.net/api/lol/na/v2.3/team/" + ID + "?api_key=myKey");
return Json(json2);
}
}
catch (Exception e)
{
text = "error";
}
return Json(new { json = text });
}
And I parsed it like normal,
$.ajax({
url: "/Competitive/teamLookUp",
type: "POST",
data: "ID=" + ID,
dataType: "json",
success: function (resp) {
if (resp["json"] == "error") {
// error reaching server
} else {
// successfully reached server
}
json = JSON && JSON.parse(resp) || $.parseJSON(resp);
var userID = ID;
teamName = json[userID].name;
teamID = json[userID].fullId;
teamCPT = json[userID].roster.ownerId;
teamTag = json[userID].tag;
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
// error
}
});
I was having the same issue as the original poster: the ReadToEnd() call result escapes special characters and thus doesn't look like JSON to the receiving end, but then I saw a similar question answered here and thought others reading this might find it helpful as well.
To summarize: Deserializing in the Controller which the original poster tried was key, but also as others have pointed out, the return doesn't need the new {} call.
So pieced together:
using (var sr = new StreamReader(endpointResponse.GetResponseStream())) {
var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
var jsonObject = serializer.DeserializeObject(sr.ReadToEnd());
return Json(jsonObject, JsonRequestBehavior.AllowGet);
}

Categories

Resources