BlobItem from an URI - .net-core

How do I get the BlobItem for which I know the full name/URI?
I have AccountName, AccountKey available to me; I can generate a SAS URI if needed.
The blobContainerClient.GetBlobs(prefix: $"{fullName}").Single(); seems the straightforward way but this is actually a query which (at scale) is costly
The BlobModelsFactory seems to be explicitly made for mocking purposes
BlobItem does not have a constructor nor publicly settable properties

You can try the code below to get the properties of a blob:
var blobClient = new BlobClient(new Uri("<Blob URI with sas token>"));
var blobProperties = blobClient.GetProperties().Value;

Related

POST method to upload file to Azure storage - what to return

I am creating an app where
user can upload the text file and then
find most used word and change that word in text and
show the changed text to the user.
if it is possible, I would like to
get the file’s text content before uploading when Post method is being called and save that content
so I add the “DownloadTextAsync()” method inside of the POST method, but it seems like I am calling this method to the wrong subject?
[HttpPost("UploadText")]
public async Task<IActionResult> Post(List<IFormFile> files)
{
string connectionString = Environment.GetEnvironmentVariable("mykeystringhere");
// Create a BlobServiceClient object which will be used to create a container client
BlobServiceClient blobServiceClient = new BlobServiceClient(connectionString);
//Create a unique name for the container
string containerName = "textdata" + Guid.NewGuid().ToString();
// Create the container and return a container client object
BlobContainerClient containerClient = await blobServiceClient.CreateBlobContainerAsync(containerName);
// Create a local file in the ./data/ directory for uploading and downloading
string localPath = "./data/";
string fileName = "textfiledata" + Guid.NewGuid().ToString() + ".txt";
string localFilePath = Path.Combine(localPath, fileName);
// Get a reference to a blob
BlobClient blobClient = containerClient.GetBlobClient(fileName);
// Open the file and upload its data
using FileStream uploadFileStream = System.IO.File.OpenRead(localFilePath);
await blobClient.UploadAsync(uploadFileStream, true);
uploadFileStream.Close();
string downloadFilePath = localFilePath.Replace(".txt", "DOWNLOAD.txt");
// Get the blob file as text
string contents = blobClient.DownloadTextAsync().Result;
//return the string
return contents;
//if (uploadSuccess)
// return View("UploadSuccess");
//else
// return View("UploadError");
}
The issues I am having are
I understood that ‘blobClient’ is the reference to the blob, where I can get the file’s data but this must be wrong?
Also it seems like I cannot use “CloudBlobContainer” nor the “CloudBlockBlob blob”. Is it because inside of the POST method, the blob has been just initialized and does not exist when these twos are executed?
Also when I test the POST method, the console throws “Refused to load the font '' because it violates the following Content Security Policy directive: "default-src 'none'". Note that 'font-src' was not explicitly set, so 'default-src' is used as a fallback.” which I googled but have no idea what it means?
I have tried different ways but keep getting CANNOT POST/“ But could not really find the solid anwers. Could this be related to my POST method?
I understood that ‘blobClient’ is the reference to the blob, where I
can get the file’s data but this must be wrong?
That's correct in a sense that you can use blobClient to perform operations on blob like upload/download etc. I am not sure why you say but this must be wrong.
Also it seems like I cannot use “CloudBlobContainer” nor the
“CloudBlockBlob blob”. Is it because inside of the POST method, the
blob has been just initialized and does not exist when these twos are
executed?
No, this is happening because you're using a newer version of SDK (version 12.x.x) and CloudBlobContainer and CloudBlockBlob are available in the older version of the SDK.
Also when I test the POST method, the console throws “Refused to load
the font '' because it violates the following Content Security Policy
directive: "default-src 'none'". Note that 'font-src' was not
explicitly set, so 'default-src' is used as a fallback.” which I
googled but have no idea what it means? I have tried different ways
but keep getting CANNOT POST/“ But could not really find the solid
anwers. Could this be related to my POST method?
Not sure why this is happening. You may want to ask a separate question for this and when you do, please include the HTML portion of your code as well.

How do I add a Dictionary<string,string> to an existing JSON.Net's JObject?

I've got a JObject (using JSON.Net) that I created by parsing some JSON text. I'm directly manipulating, adding keys at the top level of this JObject. I have no problems when the value I'm adding is a string:
json["newkey"] = "New Value"; // works
But I'll be damned if I can figure out how to add a Dictionary, e.g.:
Dictionary<string,string> dict = new Dictionary<string,string>();
dict["one"] = "1";
dict["two"] = "2";
json["dict"] = dict; // fails
I've done quite a bit of googling and reading the JSON.Net docs, but everything seems oriented towards reason JSON text into a JObject, or writing .NET objects as JSON text using serialization. Or using some fancy LINQ statements to do all kinds of things with complex objects...
I've tried these and none have worked:
json["dict"] = new JObject(dict);
json["dict"] = new JObject((Dictionary<string,string>)dict);
json["dict"] = new JArray(dict); // desperation sets in :)
json["dict"] = (JObject)dict; // please dear god let this work
Most of the latest errors I encounter are:
Could not determine JSON object type for type System.Collections.Generic.KeyValuePair`2[System.String,System.String].
I believe that you are looking for something like this:
json["dict"] = JObject.FromObject(dict);
There is a desperate "hack" that you can use, it's not pretty (doing twice the same thing) but it works :)
json["dict"] = JObject.Parse(JsonConvert.SerializeObject(dict));

Multiple instances of views in PureMVC: Am I doing this right?

What I'm doing NOW:
Often multiple instances of the view component would be used in multiple places in an application. Each time I do this, I register the same mediator with a different name.
When a notification is dispatched, I attach the name of the mediator to the body of the notification, like so:
var obj:Object = new Object();
obj.mediatorName = this.getMediatorName();
obj.someParameter = someParameter;
sendNotification ("someNotification", obj);
Then in the Command class, I parse the notification body and store the mediatorName in the proxy.
var mediatorName:String = notification.getBody().mediatorName;
var params:String = notification.getBody().someParameter;
getProxy().someMethod(params, mediatorName);
On the return notification, the mediatorName is returned with it.
var obj:Object = new Object();
obj.mediatorName = mediatorName;
obj.someReturnedValue= someReturnedValue;
sendNotification ("someReturnedNotification", obj);
In the multiple mediators that might be watching for "someReturnedNotification," in the handleNotification(), it does an if statement, to see
if obj.mediatorName == this.getMediatorName
returns true. If so, process the info, if not, don't.
My Question is:
Is this the right way of using Multiton PureMVC? My gut feeling is not. I am sure there's a better way of architecting the application so that I don't have to test for the mediator's name to see if the component should be updated with the returned info.
Would someone please help and give me some direction as to what is a better way?
Thanks.
I checked with Cliff (the puremvc.org guy) and he said it's fine.

Send parameters in order in HTTPService

I am trying to work with a simple HTTPService. The problem is that my webservice is conscious of the order of arguments it gets. I will tell the problem with an example:
var service:HTTPService = new HTTPService();
var params:Object = new Object();
params.rows = 0;
params.facet = "true";
service.send(params);
Note that in the above code I have mentioned the parameter rows before facet, but the url I recieve is facet=true&rows=0. So I recieve the argument rows before facet and hence my webservice does not work. I figured out that the contents of array is always sent in alphabetical order, which I dont want.
Is there any way I can achieve explict ordering of parameters sent?
Note that I am not in power of changing the logic of webservice(its basically a RPC service supporting both desktop and web client).
Thanks.
I am assuming you are using a get method. Instead of passing params to the HTTPService, build a url string. You can pass get params just by changing that string then calling the service.
service.url = "originalURL" + "?" + "rows=0" + "&" + "facet=true";
service.send();

Modify request querystring parameters to build a new link without resorting to string manipulation

I want to dynamically populate a link with the URI of the current request, but set one specific query string parameter. All other querystring paramaters (if there are any) should be left untouched. And I don't know in advance what they might be.
Eg, imagine I want to build a link back to the current page, but with the querystring parameter "valueOfInterest" always set to be "wibble" (I'm doing this from the code-behind of an aspx page, .Net 3.5 in C# FWIW).
Eg, a request for either of these two:
/somepage.aspx
/somepage.aspx?valueOfInterest=sausages
would become:
/somepage.aspx?valueOfInterest=wibble
And most importantly (perhaps) a request for:
/somepage.aspx?boring=something
/somepage.aspx?boring=something&valueOfInterest=sausages
would preserve the boring params to become:
/somepage.aspx?boring=something&valueOfInterest=wibble
Caveats: I'd like to avoid string manipulation if there's something more elegant in asp.net that is more robust. However if there isn't something more elegant, so be it.
I've done (a little) homework:
I found a blog post which suggested copying the request into a local HttpRequest object, but that still has a read-only collection for the querystring params. I've also had a look at using a URI object, but that doesn't seem to have a querystring
This will work as long as [1] you have a valid URL to begin with (which seems reasonable) [2] you make sure that your new value ('sausages') is properly escaped. There's no parsing, the only string manipulation is to concatenate the parameters.
Edit
Here's the C#:
UriBuilder u = new UriBuilder(Request.Url);
NameValueCollection nv = new NameValueCollection(Request.QueryString);
/* A NameValueColllection automatically makes room if this is a new
name. You don't have to check for NULL.
*/
nv["valueOfInterest"] = "sausages";
/* Appending to u.Query doesn't quite work, it
overloaded to add an extra '?' each time. Have to
use StringBuilder instead.
*/
StringBuilder newQuery = new StringBuilder();
foreach (string k in nv.Keys)
newQuery.AppendFormat("&{0}={1}", k, nv[k]);
u.Query = newQuery.ToString();
Response.Redirect(u.Uri.ToString());
UriBuilder u = new UriBuilder(Request.Url);
NameValueCollection nv = new NameValueCollection(Request.QueryString);
nv["valueofinterest"] = "wibble";
string newQuery = "";
foreach (string k in nv.Keys)
{
newQuery += k + "=" + nv[k] + "&";
}
u.Query = newQuery.Substring(0,newQuery.Length-1);
Response.Redirect(u.ToString());
that should do it
If you can't find something that exists to do it, then build a bullet-proof function to do it that is thoroughly tested and can be relied upon. If this uses string manipulation, but is efficient and fully tested, then in reality it will be little different to what you may find any way.

Resources