I have a requirement from the client to create 2 Media Libraries and Link them to 2 different Azure storage containers. I tried the following code but it still saves the files into the same container. Doesn't matter to which media library I upload files to, it always saves to the same container (ConfigurationManager.AppSettings["CMSAzureContainerName"]).
string[] subDirectories = new string[] { "cms", "memberdocuments" };
if (subDirectories != null)
{
for (int i = 0; i < subDirectories.Length; i++)
{
if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["CMSAzureMemberDocsContainerName"]) &&
subDirectories[i].ToLower().Contains("memberdocuments"))
{
var mediaProvider = StorageProvider.CreateAzureStorageProvider();
mediaProvider.CustomRootPath = ConfigurationManager.AppSettings["CMSAzureMemberDocsContainerName"];
mediaProvider.PublicExternalFolderObject = false;
StorageHelper.MapStoragePath("~/rthealth", mediaProvider);
}
else if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["CMSAzureAccountName"]))
{
var mediaProvider = StorageProvider.CreateAzureStorageProvider();
mediaProvider.CustomRootPath = ConfigurationManager.AppSettings["CMSAzureContainerName"];
mediaProvider.PublicExternalFolderObject = false;
StorageHelper.MapStoragePath("~/rthealth", mediaProvider);
}
}
}
Any tips to fix this?
You need to create new storage provider instance for each folder. Something like:
string contentContainer = "container1";
// Creates a new StorageProvider instance
var coreStorageProvider = new StorageProvider("Azure", "CMS.AzureStorage")
{
// Specifies the target container which should represent the site/codebase
CustomRootPath = contentContainer
};
// Maps a directory to the provider
StorageHelper.MapStoragePath("~/foo1", coreStorageProvider);
string contentContainer = "container2";
// Creates a new StorageProvider instance
var coreStorageProvider = new StorageProvider("Azure", "CMS.AzureStorage")
{
// Specifies the target container which should represent the site/codebase
CustomRootPath = contentContainer
};
// Maps a directory to the provider
StorageHelper.MapStoragePath("~/foo2", coreStorageProvider);
Related
I am trying to write a Blazor WebAssembly (WASM) app that accepts some code (from some text input field) and compiles the code using Roslyn.
I'm using Roslyn's CSharpCompilation class to create the compilation. Its Create method takes four parameters, one of which is a list of MetadataReferences (aka assembly references). In other (non-blazor) type applications, like a C# console app, you could get these MetadataReferences based on Asssembly Location, like this:
var locatedAssemblies = AppDomain.CurrentDomain.GetAssemblies().Where(a => !string.IsNullOrEmpty(a.Location)).ToArray();
foreach (var assembly in locatedAssemblies)
{
MetadataReference reference = MetadataReference.CreateFromFile(assembly.Location);
}
This unfortunately no longer works in Blazor WASM, because the Locations of the assemblies are empty.
I had tried getting assemblies in different ways, like AppDomain.CurrentDomain.GetAssemblies() and Assembly.GetEntryAssembly().GetReferencedAssemblies(), but all had empty Locations. I also tried calling Assembly.Load(), but to no avail.
Does anyone know how to get MetadataReferences in Blazor WASM, or how I would otherwise create a compilation in Blazor WASM?
(I'm also aware of MetadataReference.CreateFromStream() that I'll probably need to use, but it still requires the assembly location).
Thanks in advance.
I also wanted to compile C# inside a Blazor WASM app and found your question without an answer. After some digging I was able to create a working demo (repo link below.) Basically get the bytes for each assembly with HttpClient and use MetadataReference.CreateFromImage(bytes).
Full basic example repo I created: https://github.com/LostBeard/BlazorWASMScriptLoader
ScriptLoaderService.cs source:
using Microsoft.AspNetCore.Components;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Emit;
using Microsoft.CodeAnalysis.Text;
using System.Collections.Immutable;
using System.Reflection;
namespace BlazorWASMScriptLoader
{
// requires "Microsoft.CodeAnalysis.CSharp"
// can be added via nuget
public class ScriptLoaderService
{
HttpClient _httpClient = new HttpClient();
public ScriptLoaderService(NavigationManager navigationManager)
{
_httpClient.BaseAddress = new Uri(navigationManager.BaseUri);
}
async Task<MetadataReference?> GetAssemblyMetadataReference(Assembly assembly)
{
MetadataReference? ret = null;
var assmeblyName = assembly.GetName().Name;
var assemblyUrl = $"./_framework/{assmeblyName}.dll";
try
{
var tmp = await _httpClient.GetAsync(assemblyUrl);
if (tmp.IsSuccessStatusCode)
{
var bytes = await tmp.Content.ReadAsByteArrayAsync();
ret = MetadataReference.CreateFromImage(bytes);
}
}
catch { }
return ret;
}
public async Task<Assembly?> CompileToDLLAssembly(string sourceCode, string assemblyName = "")
{
if (string.IsNullOrEmpty(assemblyName)) assemblyName = Path.GetRandomFileName();
var codeString = SourceText.From(sourceCode);
var options = CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp11);
var parsedSyntaxTree = SyntaxFactory.ParseSyntaxTree(codeString, options);
var appAssemblies = Assembly.GetEntryAssembly()?.GetReferencedAssemblies().Select(o => Assembly.Load(o)).ToList();
appAssemblies.Add(typeof(object).Assembly);
var references = new List<MetadataReference>();
foreach (var assembly in appAssemblies)
{
var metadataReference = await GetAssemblyMetadataReference(assembly);
if (metadataReference == null)
{
// assembly may be located elsewhere ... handle if needed
continue;
}
var metadataReferene = metadataReference;
references.Add(metadataReferene);
}
CSharpCompilation compilation = CSharpCompilation.Create(
assemblyName,
syntaxTrees: new[] { parsedSyntaxTree },
references: references,
options: new CSharpCompilationOptions(
OutputKind.DynamicallyLinkedLibrary,
concurrentBuild: false,
optimizationLevel: OptimizationLevel.Debug
)
);
using (var ms = new MemoryStream())
{
EmitResult result = compilation.Emit(ms);
if (!result.Success)
{
IEnumerable<Diagnostic> failures = result.Diagnostics.Where(diagnostic =>
diagnostic.IsWarningAsError ||
diagnostic.Severity == DiagnosticSeverity.Error);
foreach (Diagnostic diagnostic in failures)
{
Console.Error.WriteLine("{0}: {1}", diagnostic.Id, diagnostic.GetMessage());
}
return null;
}
else
{
ms.Seek(0, SeekOrigin.Begin);
var assembly = Assembly.Load(ms.ToArray());
return assembly;
}
}
}
}
}
I am trying to read the text from a QRcode image on my mobile app. I am using Xamarin.Forms with ZXing NuGet package.
I have been able to get the file using Xamarin.Essentials FilePicker. But I don't know how to actually read the barcode. I have looked at some stackoverflow solutions and they all seem to be Xamarin.Android based (using BinaryBitmap objects). I need a solution that can work for iOS and UWP as well. Here is what I have so far:
string file = "";
var filePickerOptions = new PickOptions
{
PickerTitle = "Select Barcode Image",
FileTypes = FilePickerFileType.Images
};
var result = await FilePicker.PickAsync(filePickerOptions);
if (result != null)
{
file = result.FullPath;
var res = Decode(file, BarcodeFormat.QR_CODE);
Console.WriteLine(res.Text);
}
public Result Decode(string file, BarcodeFormat? format = null, KeyValuePair<DecodeHintType, object>[] aditionalHints = null)
{
var r = GetReader(format, aditionalHints);
/* I need some function here that will allow me to get the BinaryBitmap from the image file path or something along those lines.*/
var image = GetBinaryBitmap(file);
var result = r.decode(image);
return result;
}
MultiFormatReader GetReader(BarcodeFormat? format, KeyValuePair<DecodeHintType, object>[] aditionalHints)
{
var reader = new MultiFormatReader();
var hints = new Dictionary<DecodeHintType, object>();
if (format.HasValue)
{
hints.Add(DecodeHintType.POSSIBLE_FORMATS, new List<BarcodeFormat>() { format.Value });
}
if (aditionalHints != null)
{
foreach (var ah in aditionalHints)
{
hints.Add(ah.Key, ah.Value);
}
}
reader.Hints = hints;
return reader;
}
https://github.com/Redth/ZXing.Net.Mobile/issues/981. This thread solved it for me. Credit to #jason for this response.
I have a list with objects. Those objects all have properties. I loop through this list in the code behind. Based on a specific property of each item, I decide what view I should create.
That can be a button, picker etc.. At this moment I have reached from server to UI. But right now I need to go back from UI to server, I think that I need binding for that but I am unable to accomplish that. How can I achieve this?
My code:
var stack = new StackLayout()
{
Orientation = StackOrientation.Vertical,
Padding = 5
};
for (int i = 0; i < (BindingContext as CheckListEditViewModel).CheckListItems.Count; i++)
{
var item = (BindingContext as CheckListEditViewModel).CheckListItems[i];
var description = new Label();
description.Text = item.Description;
stack.Children.Add(description);
if ((item.ChecklistItemType == Domain.ChecklistItemType.Number))
{
var numerEntry = new Entry();
numerEntry.Keyboard = Keyboard.Numeric;
stack.Children.Add(numerEntry);
}
}
Content = stack;
I have telerik REST web API(ASP.NET ) which is working fine. Now I need to localize the reports (report are in .trdx extension).
From documentation of telerik I found the code which have place in my BaseTelerikReportsController but this also not working, and even not show any error.
Telerik Localization Documentation
public class BaseTelerikReportsController : ReportsControllerBase
{
static readonly Telerik.Reporting.Services.ReportServiceConfiguration ConfigurationInstance;
static BaseTelerikReportsController()
{
var resolver = new CustomReportResolver();
//Create new CultureInfo
var cultureInfo = new System.Globalization.CultureInfo("aa-iq"); //<-- Line 1
// Set the language for static text (i.e. column headings, titles)
System.Threading.Thread.CurrentThread.CurrentUICulture = cultureInfo; //<-- Line 2
var reportsPath = HttpContext.Current.Server.MapPath("~/Reports");
ConfigurationInstance = new Telerik.Reporting.Services.ReportServiceConfiguration
{
HostAppId = "TBReportApp",
ReportResolver = resolver,
// ReportResolver = new ReportFileResolver(reportsPath),
Storage = new Telerik.Reporting.Cache.File.FileStorage(),
};
}
public BaseTelerikReportsController()
{
ReportServiceConfiguration = ConfigurationInstance;
}
}
Note
There is a similar question but don't guide me to any right direction Here
Update 1
I have added below function in Global.asax.cs.
protected void Application_AcquireRequestState(object sender, EventArgs e)
{
//Create new CultureInfo
var cultureInfo = new System.Globalization.CultureInfo("ar");
// Set the language for static text (i.e. column headings, titles)
System.Threading.Thread.CurrentThread.CurrentUICulture = cultureInfo;
// Set the language for dynamic text (i.e. date, time, money)
System.Threading.Thread.CurrentThread.CurrentCulture = cultureInfo;
}
After above line (see image) data under red mark is localize but i need to localize yellow one(i.e heading)
I figure out how to localize the report header. Following are the some summarized steps.
Add App_GlobalResources folder and .resx accordingly your languages (See the figure 1-1).
Send language attribute from 'HTML5 Viewer'.
var viewer = $("#report-viewer").data("telerik_ReportViewer");
var model = {
//other attributes
Language: this.selectedLanguage //Here value may be ,en Or ar
};
viewer.reportSource({
report: reportSettings,
parameters: model
});
On server side based on that attribute change label accordingly.
private static void Localization(ref Report reportInstance)
{
ResourceManager currentResource = null;
switch (_language)
{
case "en":
currentResource = new ResourceManager("Resources.en", System.Reflection.Assembly.Load("App_GlobalResources"));
break;
case "ar":
currentResource = new ResourceManager("Resources.ar", System.Reflection.Assembly.Load("App_GlobalResources"));
break;
}
// var MyResourceClass = new ResourceManager("Resources.ar", System.Reflection.Assembly.Load("App_GlobalResources"));
ResourceSet resourceSet = currentResource.GetResourceSet(CultureInfo.CurrentUICulture, true, true);
foreach (DictionaryEntry entry in resourceSet)
{
string key = entry.Key.ToString();
string value = entry.Value.ToString();
var items = reportInstance.Items.Find(key,true);
foreach (var singleItem in items)
{
var singleItemType = singleItem.GetType();
//if (singleItem.GetType().FullName == "") ;
if (singleItemType.FullName == "Telerik.Reporting.TextBox")
{
var castItem = (Telerik.Reporting.TextBox) singleItem;
castItem.Value = value;
}
}
}
}
On Telerik Standalone Report Designer
Change your report(.trdx) Textbox value which matches your .resxname value pair.
Resource file values
I am trying to connect an SQLite database file to a picker component (accepting strings). This should act similar to a drop-down menu. I have tried to follow previous advice and examples, but without success.
As indicated in a previous post, I have saved the database file in the source folder of the application. View of the source folder where I have saved the database file (highlighted).
The code I have used to implement my app is as follows with the below layout.
//-----------------------
database code
//-----------------------
public class MyApplication {
private Form current;
private Resources theme;
public void init(Object context) {
theme = UIManager.initFirstTheme("/theme");
// Pro only feature, uncomment if you have a pro subscription
// Log.bindCrashProtection(true);
}
private Container Home() {
Container home = new Container(new BoxLayout(BoxLayout.Y_AXIS));
return home;
}
private Container AddItem() {
Container addItem = new Container(new BoxLayout(BoxLayout.Y_AXIS));
TextArea item = new TextArea("Add Item");
addItem.addComponent(item);
Picker selectItem = new Picker();
selectItem.setType(Display.PICKER_TYPE_STRINGS);
//----------------------------------------------------------------------------------
Database db = null;
Cursor cur = null;
try {
db = Display.getInstance().openOrCreate("FoodAndBeverage.db");
if(selectItem.getText().startsWith("Still Water")) {
cur = db.executeQuery(selectItem.getText());
int columns = cur.getColumnCount();
addItem.removeAll();
if(columns > 0) {
boolean next = cur.next();
if(next) {
ArrayList<String[]> data = new ArrayList<>();
String[] columnNames = new String[columns];
for(int iter = 0 ; iter < columns ; iter++) {
columnNames[iter] = cur.getColumnName(iter);
}
while(next) {
Row currentRow = cur.getRow();
String[] currentRowArray = new String[columns];
for(int iter = 0 ; iter < columns ; iter++) {
currentRowArray[iter] = currentRow.getString(iter);
}
data.add(currentRowArray);
next = cur.next();
}
Object[][] arr = new Object[data.size()][];
data.toArray(arr);
addItem.add(BorderLayout.CENTER, new Table(new DefaultTableModel(columnNames, arr)));
} else {
addItem.add(BorderLayout.CENTER, "Query returned no results");
}
} else {
addItem.add(BorderLayout.CENTER, "Query returned no results");
}
} else {
db.execute(selectItem.getText());
addItem.add(BorderLayout.CENTER, "Query completed successfully");
}
addItem.revalidate();
} catch(IOException err) {
Log.e(err);
addItem.removeAll();
addItem.add(BorderLayout.CENTER, "Error: " + err);
addItem.revalidate();
} finally {
Util.cleanup(db);
Util.cleanup(cur);
}
//---------------------------------------------------------------------------------------------
addItem.addComponent(selectItem);
TextField quantity = new TextField("", "Quantity (ml or g)", 4, TextArea.NUMERIC);
addItem.addComponent(quantity);
Button add = new Button("Add");
addItem.addComponent(add);
TextArea results = new TextArea("Results");
addItem.addComponent(results);
return addItem;
}
private Container Settings() {
Container settings = new Container(new BoxLayout(BoxLayout.Y_AXIS));
TextArea nutrients = new TextArea("Target");
settings.addComponent(nutrients);
TextField volume = new TextField("", "Volume (ml)", 4, TextArea.NUMERIC);
settings.addComponent(volume);
TextArea duration = new TextArea("Hydration Duration");
settings.addComponent(duration);
settings.add("Start:");
Picker start = new Picker();
start.setType(Display.PICKER_TYPE_TIME);
settings.addComponent(start);
settings.add("End:");
Picker end = new Picker();
end.setType(Display.PICKER_TYPE_TIME);
settings.addComponent(end);
Button save = new Button("Save");
settings.addComponent(save);
return settings;
}
public void start() {
if(current != null)
{
current.show();
return;
}
Form home = new Form("Hydrate", new BorderLayout());
Tabs t = new Tabs();
t.addTab("Home", Home());
t.addTab("Intake", AddItem());
t.addTab("Settings", Settings());
home.add(BorderLayout.NORTH, t);
home.show();
}
public void stop() {
current = Display.getInstance().getCurrent();
}
public void destroy() {
}
}
I would therefore appreciate any advice and guidance on exactly where I am going wrong and how to implement the suggested changes in my code.
I'm assuming the file under src does indeed end with the extension db as the Windows hidden extensions nonsense is turned on.
This code will NOT open a db placed in src:
db = Display.getInstance().openOrCreate("FoodAndBeverage.db");
You need to do something like this to implicitly initialize the DB the first time the app is installed:
String path = Display.getInstance().getDatabasePath("FoodAndBeverage.db");
FileSystemStorage fs = FileSystemStorage.getInstance();
if(!fs.exists(path)) {
try (InputStream is = Display.getInstance().getResourceAsStream(getClass(), "/FoodAndBeverage.db");
OutputStream os = fs.openOutputStream(path)) {
Util.copy(is, os);
} catch(IOException err) {
Log.e(err);
}
}
db = Display.getInstance().openOrCreate("FoodAndBeverage.db");
Notice that the code above doesn't check for updates of the DB so assuming the DB is read only you might want to update/merge it with app updates.
The above code doesn't work on Android device, this works only on simulator. I have tested multiple times in the android device. In the real android device ,the database is not loaded at all, shows sql exception error
"No such table sql exception".
Looks like preloaded sqlite .db file is never tested on real Android device.