I'm trying to save two images in the azure blob, but I can only save one.
follow my example:
In the example I have two fields with an image, the idea is to select an image for each card
enter image description here
But my control is prepared to save only one image, how can I add only two images?
my blob flow:
inside the service folder I have a folder called blob that contains 3 classes ( blob, FileUpload, IBlob )
Image of the blob structure
Class Blob:
namespace Services.Blob
{
public class Blob
{
private static string _connectionAzure = "DefaultEndpointsProtocol=*******";
/// <summary>
/// Uploads de arquivos / blob assíncronos.
/// </summary>
/// <returns>Método que vai efetuar o upload da foto da pessoa no Blob Storage.</returns>
/// <param name="file"></param>
/// <returns></returns>
public static async Task<string> UploadBlobFileAsync(IFormFile file)
{
// Recupera a connection string da variável de ambiente que definimos no appsettings.
var contaStorage = CloudStorageAccount.Parse(_connectionAzure);
string empresa = "tijoforte";
//Variável que representa o endpoint do blob storage account.
var endPointBlob = contaStorage.CreateCloudBlobClient();
//Tenta recuperar o container em que será salvo o blob, se não existir ele cria.
// Regras: O nome do container não deve conter letras maíuscúlas.
var container = endPointBlob.GetContainerReference(empresa); // Nota que aqui vamos passar o nome de cada empresa para criar o contatiner no azure.
await container.CreateIfNotExistsAsync();
//Recupera a referência do endereço do blob e faz o upload do mesmo.
var blockBlob = container.GetBlockBlobReference(file.FileName);
using (var fileStream = file.OpenReadStream())
{
await blockBlob.UploadFromStreamAsync(fileStream);
}
return blockBlob.Uri.ToString();
}
/// <summary>
/// Salva o nome, e-mail e documento específico.
/// </summary>
/// <returns>Método que salva os dados cadastrados nas tabelas do Storage do Azure</return>
/// <param name="nome">Nome</param>
/// <param name="email">E-mail</param>
/// <param name="documentoUrl">Documento.</param>
/// <returns></returns>
public static async Task Salvar(string id, string nome, string documentoUrl, string tabela)
{
//Recupera a connection strung da variável de ambiente que definimos no appsettings
var contaStorage = CloudStorageAccount.Parse(_connectionAzure);
//Cria o client para a tabela.
var tableClient = contaStorage.CreateCloudTableClient();
//Tenta recuperar objeto que representará a tabela, se não existir ela cria.
//O nome da tabela não deve conter letras maíuscúlas.
var table = tableClient.GetTableReference(tabela.ToLower());
await table.CreateIfNotExistsAsync();
//Cria o objeto da entidade.
var retorno = new BlobStorage(id, nome);
retorno.FotoBlob = documentoUrl;
//Efetua a inserção da tabela no azure do CDevs.
var tableOperation = TableOperation.InsertOrReplace(retorno);
await table.ExecuteAsync(tableOperation);
}
}
}
Class FileUpload:
namespace Services.Blob
{
public class FileUpload
{
public string UploadBase64Image(string base64Image, string container)
{
// Gerra um nome randomico para a imagem.
var fileName = Guid.NewGuid().ToString() + ".jpg";
// Limpa o has enviado
var data = new Regex(#"^data:image\/[a-z]+;base64,").Replace(base64Image, "");
// Gera um array de bytes
byte[] imageBytes = Convert.FromBase64String(data);
// Define o blob no qual a imagem será armazenada.
var blobClient = new BlobClient("DefaultEndpointsProtocol=****", container, fileName);
using (var stream = new System.IO.MemoryStream(imageBytes))
{
blobClient.Upload(stream);
}
// retorna a url do blob
return blobClient.Uri.AbsoluteUri;
}
}
}
Interface IBlob
namespace Services.Blob
{
public interface IBlob
{
/// <summary>
/// Criação do métodos de uploads, salvar e listar.
/// </summary>
public interface IBlob
{
Task<string> UploadBlobFileAsync(IFormFile file);
Task Salvar(string nome, string email, string documentoUrl);
Task<List<BlobStorage>> Lista();
}
}
}
After this process, the blob is ready to use.
But it doesn't work if I want it for just two images
Controller WEB:
Web application structure
Controller:
try
{
// tratamento para salvar no blob
if (file != null)
{
//THE PROBLEM IS HERE ONLY SAVES ONE IMAGE
var urlBlob = await Blob.UploadBlobFileAsync(file);
await Blob.Salvar(blog.BlogId.ToString(), blog.Nome, urlBlob, nameof(Blog).ToLower());
blog.ImagemPequena = urlBlob;
}
// Realiza processo de alteração
var retorno = await Blog().Alterar(blogId, blog);
return RedirectToAction("Formulario", new { mensagem = $"Registro alterado com sucesso! {blog.Nome}" });
}
catch (Exception)
{
throw;
}
**
WHAT AM I DOING WRONG?
**
To achieve the above requirement you can find the sample code here in this GitHub , which saves four files together in blob storage , Instead of that you can use two images to be saved in your blob storage as well.
OUTPUT FOR REFERENCE:-
For more information please refer the below links:-
SO THREAD:- How to upload Multiple Files in Blob storage in DotNetCore as suggested by #Gaurav Mantri
BLOG:- Upload Multiple Images In Azure Blob Storage
Related
I have a problem with my WPF app.
After I release it with "Create App Package" in VS and then start the app, it does not save the data in the Json file.
Here is the Class I use to save the Trades:
public class JsonSaver : ISaver
{
#region Property
/// <summary>
/// Pfad zur Json Datei (ab Current Directory)
/// </summary>
public static string Path = String.Format(Directory.GetCurrentDirectory() + #"data\Trades.json");
#endregion
#region Methoden
/// <summary>
/// Ladet alle Trades von der Json datei(siehe Property "path") in eine ObservableCollection
/// </summary>
/// <returns>ObservableCollection mit allen Trades</returns>
public ObservableCollection<Trade> loadTrades()
{
try
{
if (!File.Exists(Path))
{
var w = File.Open(Path, FileMode.Create);
w.Close();
}
using (StreamReader r = new StreamReader(Path))
{
string json = r.ReadToEnd();
if (json == "")
{
return new ObservableCollection<Trade>();
}
r.Close();
return JsonConvert.DeserializeObject<ObservableCollection<Trade>>(json);
}
}
catch (Exception)
{
return new ObservableCollection<Trade>();
}
}
/// <summary>
/// Speicher alle Trades in der Json Datei(siehe Property "path")
/// </summary>
/// <param name="allTrades">ObservableCollection mit den zu speichernden Trades</param>
/// <returns>True / False je nach erfolg</returns>
public bool saveTrades(ObservableCollection<Trade> allTrades)
{
try
{
using (StreamWriter w = new StreamWriter(Path, false))
{
string json = JsonConvert.SerializeObject(allTrades);
w.Write(json);
w.Close();
}
return true;
}
catch (Exception)
{
return false;
}
}
#endregion
}
The method "loadTrades" is called everytime the app opens.
The method "saveTrades" is called everytime the app is closed. (MainWindow: Onclosing)
The Json file "Trades.json" is in the correct folder after I install it:
Directory of the app (found with the Task-Manager)
Json File
Everything works when I debug it in VS but not after I release it.
Thanks for the help. If you need more information, feel free to ask.
Simon
This question already has answers here:
Newtonsoft.Json deserialize object in Xamarin iOS project
(6 answers)
Closed 4 years ago.
I have this code in a Xamarin type solution
public async Task<Response> GetList<Publication>(string urlBase, string servicePrefix, string controller)
{
try
{
var client = new HttpClient();
client.BaseAddress = new Uri(urlBase);
var url = string.Format("{0}{1}", servicePrefix, controller);
var response = await client.GetAsync(url);
var result = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
{
return new Response
{
IsSuccess = false,
Message = result,
};
}
var list = JsonConvert.DeserializeObject<List<Publication>>(result);
return new Response
{
IsSuccess = true,
Message = "Ok",
Result = list,
};
}
catch (Exception ex)
{
return new Response
{
IsSuccess = false,
Message = ex.Message,
};
}
}
when I debug it, JsonConvert.DeserializeObject<List<Publication>>(result); doesn't work, return null...
DEBUG IN XAMARIN
I'm sure result is not null
But if I run the same code in a console type solution, It Works!!!
I'm using the same class, there is my Publication class
public class Publication
{
public int IdPublicacion { get; set; }
public string UrlVideo { get; set; }
public object UrlImagen { get; set; }
public string Text { get; set; }
public string Titulo { get; set; }
public DateTime Fecha { get; set; }
public string Sacerdote { get; set; }
}
And there is my Json Code
[
{
"IdPublicacion": 1,
"UrlVideo": "https://www.youtube.com/watch?v=mQR0bXO_yI8",
"UrlImagen": null,
"Text": "Para fomentar la lectura en los niños es recomendable empezar con cuentos infantiles cortos que traten de aventuras divertidas y que capten la atención de los niños. De esta forma, los niños se divertirán a la vez que empiezan a cogerle el gusto a la lectura.\r\n \r\nLos relatos cortos con son los mejores para empezar a leer con los niños. Aunque hay multitud de cuentos tradicionales que son esenciales y que todo niño debería conocer, ya que han ido pasando de generación en generación.\r\n\r\nEn pequelandia.org se han seleccionado una serie de cuentos infantiles cortos para leer con niños. Son relatos cortos para hacer de la lectura un momento agradable y divertido, de forma que los niños empiecen a familiarizarse con la lectura y los libros.",
"Titulo": "Fly me to the moon",
"Fecha": "2018-03-07T00:00:00",
"Sacerdote": "Julian"
},
{
"IdPublicacion": 2,
"UrlVideo": "https://www.youtube.com/watch?v=mQR0bXO_yI8",
"UrlImagen": null,
"Text": "Para fomentar la lectura en los niños es recomendable empezar con cuentos infantiles cortos que traten de aventuras divertidas y que capten la atención de los niños. De esta forma, los niños se divertirán a la vez que empiezan a cogerle el gusto a la lectura.\r\n \r\nLos relatos cortos con son los mejores para empezar a leer con los niños. Aunque hay multitud de cuentos tradicionales que son esenciales y que todo niño debería conocer, ya que han ido pasando de generación en generación.",
"Titulo": "Titulo 2",
"Fecha": "2018-03-06T00:00:00",
"Sacerdote": "Julian"
}]
Additional information, when I see the List, show a message
"Unable to cast object of type 'System.RuntimeType' to type 'Mono.Debugger.Soft.TypeMirror'."
Finally there is my GitHub project https://github.com/solartes/VesApp
SOLVED.
THE PROBLEM? JSON.NET has problem with the Xamarin Live Player, so it doesn't works if you play it in Xamarin Live Player, you have to run it in Android Simulator.
Try to add Preserve attribute to the Publication class:
[Preserve(AllMembers = true)]
public class Publication
It might happen that the build strips out the properties of the class and hence they are missing and cannot be deserialized.
I realized that in your Debug you did not specify the type that you want to deserialize your json to List< T >. However, in your test that worked, you did specify that you need a list of Publications back "List< Publication >" .
I am using httpclient to get data from an Api Rest through Xamarin. My problem happens when I'm going to run httpclient again on a new page to get back the api information, that is, this works only once, how do I solve it?
Code:
private async void ObterNoticiasXbox()
{
var respXbox = string.Empty;
try
{
var uriXbox = new HttpClient()
{
BaseAddress = new Uri("http://api.newsplay.com.br")
};
var urlXbox = "/post/";
var resultXbox = await uriXbox.GetAsync(urlXbox);
if (!resultXbox.IsSuccessStatusCode)
{
await DisplayAlert("Erro de Conexão", "Não foi possível obter as notícias do servidor, Tente novamente mais tarde!", "OK");
return;
}
respXbox = await resultXbox.Content.ReadAsStringAsync();
}
catch (Exception ex)
{
await DisplayAlert("Erro de Conexão com o Servidor", ex.Message, "OK");
return;
}
// transformando o retorno em objeto através do json e deserealize e retornando em lista
var NXbox = JsonConvert.DeserializeObject<List<XboxModels>>(respXbox);
//Adicionando os itens ao ListView na Home.xaml
XboxList.ItemsSource = NXbox;
}
}
I am looking to loop through all SAP GuiComponents in c# but am struggling to get all the children of children of a gui session.
This is what I have so far (initially passing session.ActiveWindow.Children to nodes):
private void IterateFindIDByNAme(GuiComponentCollection nodes, string searchstring)
{
if (foundID == "")
{
foreach (GuiComponent node in (GuiComponentCollection)nodes)
{
var comp = node;
if (comp.Name.Contains(searchstring))
foundID = comp.Id;
else
{
try
{
FindIDByNAme((GuiComponentCollection)node, searchstring);
}
catch { }
}
}
}
}
Its able to get all the child elements of session.ActiveWindow but when trying to cast all the children to GuiComponentCollections its falling over.
This would be irrelevant if I could use the FindByName function but for some reason it is not working on the SAP screen i am currently working on (it does work on others, not sure why).
The ID of the field is:
wnd[0]/usr/subBCA_SUB_HEADER:SAPLBANK_BDT_CTRL:0100/subSUBS_DETAIL:SAPLBUSS:0028/ssubGENSUB:SAPLBUSS:4038/subA01P02:SAPLBCA_DYN_CN_CNMANO:0002/ctxtBCA_DYN_CONTRACT_ORGENTRY-ORGUNIT
and the function I am trying is:
((GuiTextField)session.FindByName("BCA_DYN_CONTRACT_ORGENTRY-ORGUNIT", "GuiTextField")).Text = "Test";
The findbyid works fine, but not findbyname?
I know this is 2 questions, but kind of related.
ctxtBCA_DYN_CONTRACT_ORGENTRY-ORGUNIT
The type of the control is a GuiCTextField not GuiTextField:
session.FindByName("BCA_DYN_CONTRACT_ORGENTRY-ORGUNIT", "GuiCTextField")
Sample Code :
public DateTime? GetModificationDate(int employeeID)
{
var session = SapHelper.GetActiveSession();
Console.WriteLine("Recherche de la measure [A5 ou A6] avec un motif 90...");
var window = session.BeginTransaction("PA20", "Afficher données de base personnel");
window.FindByName<GuiCTextField>("RP50G-PERNR").Text = employeeID.ToString();
window.FindByName<GuiCTextField>("RP50G-CHOIC").Text = "Mesures (0000)";
window.FindByName<GuiCTextField>("RP50G-SUBTY").Text = null;
window.FindByName<GuiButton>("btn[20]").Press(); // list view
if (window.Text == "Afficher données de base personnel")
{
Console.WriteLine(">> " + window.FindByName<GuiStatusbar>("sbar").Text);
return null;
}
/* Index Type Title Tooltip
0 GuiTextField Début Date de début
1 GuiTextField Fin Date de fin
2 GuiCTextField Mes. Catégorie de mesure
3 GuiTextField Dés. cat. mesure Dés. cat. mesure
4 GuiCTextField MotMe Motif mesure
5 GuiTextField Dés. motif mesure Dés. motif mesure
6 GuiCTextField Client Statut propre client
7 GuiCTextField Activité Statut d'activité
8 GuiCTextField Paiement Statut paiement part */
var result = window.FindByName<GuiTableControl>("MP000000TC3000").AsEnumerable()
.Select(x => new
{
Start = x.GetText(0),
Category = x.GetCText(2),
CategoryText = x.GetText(3),
Reason = x.GetCText(4),
ReasonText = x.GetText(5),
})
.Where(x => (x.Category == "A5" || x.Category == "AG") && x.Reason == "90")
.FirstOrDefault();
if (result == null)
{
Console.WriteLine(">> aucune measure [A5 ou A6] avec un motif 90 trouvée");
return null;
}
else
{
Console.WriteLine(">> {0}:[{1}]{2} [{3}]{4}",
result.Start, result.Category, result.Category, result.Reason, result.ReasonText);
return DateTime.ParseExact(result.Start, "yyyy/MM/dd", CultureInfo.InvariantCulture);
}
}
Xy.Sap :
#region namespace Xy.Sap
namespace Xy.Sap
{
using System.Reflection;
using sapfewse;
using saprotwr.net;
using COMException = System.Runtime.InteropServices.COMException;
public static class SapHelper
{
public static GuiSession GetActiveSession()
{
var rot = new CSapROTWrapper().GetROTEntry("SAPGUI");
if (rot == null)
throw SapException.NotOpened();
var app = (GuiApplication)rot.GetType().InvokeMember("GetScriptingEngine", BindingFlags.InvokeMethod, null, rot, null);
var connectedSession = app.Connections.Cast<GuiConnection>()
.SelectMany(x => x.Children.Cast<GuiSession>())
.Where(x => !string.IsNullOrEmpty(x.Info.User))
.FirstOrDefault();
if (connectedSession == null)
throw SapException.NotOpened();
return connectedSession;
}
}
public class SapException : Exception
{
public SapException(string message) : base(message) { }
public static SapException NotOpened()
{
return new SapException("Veuillez lancer le SAP et de connecter avec votre identité");
}
}
public static class SapExtensions
{
#region GuiSession
/// <summary>
/// Shortcut for PA20 query
/// </summary>
/// <param name="session"></param>
/// <param name="employeeID"></param>
/// <param name="it">Infotype ID</param>
/// <param name="sty">Subtype ID</param>
/// <param name="asListView"></param>
/// <returns></returns>
public static GuiFrameWindow QueryPA20(this GuiSession session, int employeeID, string it, string sty = null, bool asListView = false)
{
var window = session.BeginTransaction("PA20", "Afficher données de base personnel");
window.FindByName<GuiCTextField>("RP50G-PERNR").Text = employeeID.ToString();
window.FindByName<GuiCTextField>("RP50G-CHOIC").Text = it;
window.FindByName<GuiCTextField>("RP50G-SUBTY").Text = sty;
window.FindByName<GuiButton>(asListView ? "btn[20]" : "btn[7]").Press();
if (window.Text == "Afficher données de base personnel")
{
var exception = new InvalidOperationException(string.Format("Failed to access to personal information of {0}", employeeID));
exception.Data["Employee ID"] = employeeID;
exception.Data["Infotype"] = it;
exception.Data["Subtype"] = sty;
exception.Data["View"] = asListView ? "ListView[Mont]" : "RecordView[Glasses]";
exception.Data["Status Message"] = window.FindByName<GuiStatusbar>("sbar").Text;
throw exception;
}
return window;
}
/// <summary>
/// Shortcut for PA30 query
/// </summary>
/// <param name="session"></param>
/// <param name="employeeID"></param>
/// <param name="it">Infotype ID</param>
/// <param name="sty">Subtype ID</param>
/// <param name="asListView"></param>
/// <returns></returns>
public static GuiFrameWindow QueryPA30(this GuiSession session, int employeeID, string it, string sty = null)
{
var window = session.BeginTransaction("PA30", "Gérer données de base HR");
window.FindByName<GuiCTextField>("RP50G-PERNR").Text = employeeID.ToString();
window.FindByName<GuiCTextField>("RP50G-CHOIC").Text = it;
window.FindByName<GuiCTextField>("RP50G-SUBTY").Text = sty;
window.FindByName<GuiButton>("btn[6]").Press();
if (window.Text == "Gérer données de base HR")
{
var exception = new InvalidOperationException(string.Format("Failed to access to personal information of {0}", employeeID));
exception.Data["Employee ID"] = employeeID;
exception.Data["Infotype"] = it;
exception.Data["Subtype"] = sty;
exception.Data["Status Message"] = window.FindByName<GuiStatusbar>("sbar").Text;
throw exception;
}
return window;
}
/// <summary>
/// Start a new transaction and return the active window
/// </summary>
public static GuiFrameWindow BeginTransaction(this GuiSession session, string transactionID, string expectedTitle)
{
return session.BeginTransaction(transactionID,
x => x.Text == expectedTitle,
x =>
{
var exception = new InvalidOperationException(string.Format("Failed to open transaction : {0}", transactionID));
exception.Data["Transaction ID"] = transactionID;
exception.Data["Expected Title"] = expectedTitle;
exception.Data["Current Title"] = x.Text;
exception.Data["Status Message"] = x.FindByName<GuiStatusbar>("sbar").Text;
return exception;
});
}
public static GuiFrameWindow BeginTransaction(this GuiSession session, string transactionID, Predicate<GuiFrameWindow> validation, Func<GuiFrameWindow, string> errorFormatter)
{
return session.BeginTransactionImpl(transactionID, validation, x => new Exception(errorFormatter(x)));
}
public static GuiFrameWindow BeginTransaction(this GuiSession session, string transactionID, Predicate<GuiFrameWindow> validation, Func<GuiFrameWindow, Exception> errorBuilder)
{
return session.BeginTransactionImpl(transactionID, validation, errorBuilder);
}
private static GuiFrameWindow BeginTransactionImpl(this GuiSession session, string transactionID, Predicate<GuiFrameWindow> validation, Func<GuiFrameWindow, Exception> errorBuilder)
{
// force current transaction to end, preventing any blocking(eg: model dialog)
session.EndTransaction();
session.StartTransaction(transactionID);
var window = session.ActiveWindow;
if (!validation(window))
throw errorBuilder(window);
return window;
}
#endregion
#region GuiFrameWindow
public static TSapControl FindByName<TSapControl>(this GuiFrameWindow window, string name)
{
try
{
return (TSapControl)window.FindByName(name, typeof(TSapControl).Name);
}
catch (COMException e)
{
var writer = new StringWriter();
writer.WriteLine("The control could not be found by name and type.");
writer.WriteLine("Name : " + name);
writer.WriteLine("Type : " + typeof(TSapControl).Name);
throw new Exception(writer.ToString(), e);
}
}
#endregion
#region GuiTableControl
/// <summary>Note: Do not iterate through this ienumerable more than once</summary>
public static IEnumerable<GuiTableRow> AsEnumerable(this GuiTableControl table)
{
var container = table.Parent as dynamic;
string name = table.Name, type = table.Type;
int rowCount = table.VerticalScrollbar.Maximum;
Func<GuiTableControl> getTable = () => container.FindByName(name, type) as GuiTableControl;
for (int i = 0; i <= rowCount; i++)
{
getTable().VerticalScrollbar.Position = i;
yield return getTable().Rows.Item(0) as GuiTableRow;
}
}
public static TSapControl GetCell<TSapControl>(this GuiTableRow row, int column)
{
return (TSapControl)row.Item(column);
}
public static string GetCText(this GuiTableRow row, int column)
{
return row.GetCell<GuiCTextField>(column).Text;
}
public static string GetText(this GuiTableRow row, int column)
{
return row.GetCell<GuiTextField>(column).Text;
}
#endregion
}
}
#endregion
EDIT: The link to the LINQPad script mentioned in comment below no longer works. I have re-uploaded it here.
This script helps you to browse SAP GUI:
List control type, name, id, content
List properties and methods
Highlight control
Generate selector : .FindByName<GuiTableControl>("MP000000TC3000")
In case anyone wants to know how to get child elements of any gui component (this will simply write all ids to the console):
private void LoopAllElements(GuiComponentCollection nodes)
{
foreach (GuiComponent node in (GuiComponentCollection)nodes)
{
Console.WriteLine(node.Id);
if (node.ContainerType)
{
var children = ((node as dynamic).Children as GuiComponentCollection);
LoopAllElements(children);
}
}
}
This will loop through all child elements of any GUIComponentCollection you pass to it such as
LoopAllElements(session.Children)
There is probably a better linq way of doing this but this should get you started.
Please also check out this gist created by Xiaoy312 https://gist.github.com/Xiaoy312/a1424bd34acae92554105b27b0c80971
this has a lot of useful functions to debug your current sap session which i have found extremely useful.
You can either view the code as it has a number of functions you can use such as improved findbyid and findbyname or run it in linqpad https://www.linqpad.net/Download.aspx which will allow you to interogate the current SAP session.
If I understood correctly we have to manually start SAP Logon to make line below working:
var rot = new CSapROTWrapper().GetROTEntry("SAPGUI");
Am I right?
If so maybe someone can explain me why at the line:
var app = (GuiApplication)rot.GetType().InvokeMember("GetScriptingEngine", BindingFlags.InvokeMethod, null, rot, null);
I am getting exception:
An exception of type 'System.Runtime.InteropServices.COMException'
occurred in System.Dynamic.dll but was not handled in user code
Additional information: Error loading type library/DLL. (Exception
from HRESULT: 0x80029C4A (TYPE_E_CANTLOADLIBRARY))
I've already tried to change target platform from Any CPU to x86 and x64 and didn't have success in resolving this problem.
But when I run SAPGUI using following script:
var SapGuiApp = new GuiApplication();
string development = "Development ERP System";
var connection = SapGuiApp.OpenConnection(development);
instead of running SAP Logon manually described above problem is not reproducing.
But in this case I have other problem: GUI is different and for second option GUI looks corrupted - some of GUI controls are not displayed (please see screenshot). Please give me advice what can be wrong? Thank you in advance
UPDATE: I found solution that solves issue described below. You have to use object instead of var while you are trying to get session connection:
CSapROTWrapper sapROTWrapper = new CSapROTWrapper();
object rot = sapROTWrapper.GetROTEntry("SAPGUI");
object engine = rot.GetType().InvokeMember("GetScriptingEngine", System.Reflection.BindingFlags.InvokeMethod, null, rot, null);
GuiConnection connection = (engine as GuiApplication).OpenConnection(connectionName);
GuiSession session = connection.Children.ElementAt(0) as GuiSession;
I'm experiencing some trouble with BitmapImage here. I have a WP8.1 app in which I can take photo, preview it and upload it. The preview is well displayed, good rotation and size but the problem is that, to upload it, I pass the byte[] corresponding to the storageFile wich is a big and not so well oriented picture.. I would like to rotate and shrink the storageFile BEFORE getting the byte[] from it.
Here is the snippet I use to preview/take/convert the picture :)
//Récupère la liste des camèras disponibles
private static async Task<DeviceInformation> GetCameraID(Windows.Devices.Enumeration.Panel desiredCamera)
{
DeviceInformation deviceID = (await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture))
.FirstOrDefault(x => x.EnclosureLocation != null && x.EnclosureLocation.Panel == desiredCamera);
if (deviceID != null) return deviceID;
else throw new Exception(string.Format("Camera of type {0} doesn't exist.", desiredCamera));
}
//Initialise la caméra
async private void initCamera()
{
//Récupération de la caméra utilisable
var cameraID = await GetCameraID(Windows.Devices.Enumeration.Panel.Back);
//Initialise l'objet de capture
captureManager = new MediaCapture();
await captureManager.InitializeAsync(new MediaCaptureInitializationSettings
{
StreamingCaptureMode = StreamingCaptureMode.Video,
PhotoCaptureSource = PhotoCaptureSource.VideoPreview,
AudioDeviceId = string.Empty,
VideoDeviceId = cameraID.Id
});
var maxResolution = captureManager.VideoDeviceController.GetAvailableMediaStreamProperties(MediaStreamType.Photo).Aggregate((i1, i2) => (i1 as VideoEncodingProperties).Width > (i2 as VideoEncodingProperties).Width ? i1 : i2);
await captureManager.VideoDeviceController.SetMediaStreamPropertiesAsync(MediaStreamType.Photo, maxResolution);
}
//Évènmenet pour le bouton de prise de photo.
async private void previewpicture_Click(object sender, RoutedEventArgs e)
{
//Si la prévisualisation n'est pas lancée
if (EnPreview == false)
{
//On cache les élèments inutilisés.
tfComment.Visibility = Visibility.Collapsed;
vbImgDisplay.Visibility = Visibility.Collapsed;
//On met la prévisualisation dans le bon sens.
captureManager.SetPreviewRotation(VideoRotation.Clockwise90Degrees);
//On charge la prévisualisation dans l'élèment de l'image de la fenêtre.
capturePreview.Source = captureManager;
//On rend la prévisualisation possible.
capturePreview.Visibility = Visibility.Visible;
//Démarre le flux de prévisualisation
await captureManager.StartPreviewAsync();
//On précise que la prévisualisation est lancée.
EnPreview = true;
//On change le label du bouton
previewpicture.Label = "Prendre photo";
}
//Si la prévisualisation est lancée
else if (EnPreview == true)
{
//Créer le fichier de la photo depuis la mémoire interne de l'application
StorageFile photoFile = await ApplicationData.Current.LocalFolder.CreateFileAsync("myFirstPhoto.jpg", CreationCollisionOption.ReplaceExisting);
//Récupère la photo avec le format d'encodage décidé.
await captureManager.CapturePhotoToStorageFileAsync(ImageEncodingProperties.CreateJpeg(), photoFile);
// we can also take a photo to memory stream
InMemoryRandomAccessStream memStream = new InMemoryRandomAccessStream();
await captureManager.CapturePhotoToStreamAsync(ImageEncodingProperties.CreateJpegXR(), memStream);
//Debug.WriteLine(memStream.ToString());
//Récupère l'image dans un objet image qu'on peut mettre dans le container d'affichage
BitmapImage bitmapToShow = new BitmapImage(new Uri(photoFile.Path));
//Met l'image dans le container d'affichage
imgDisplay.Source = bitmapToShow;
vbImgDisplay.RenderTransform = new RotateTransform() {CenterX = 0.5, CenterY = 0.5, Angle = 90 };
//Cache la previsualisation
capturePreview.Visibility = Visibility.Collapsed;
//Arrête le flux de prévisualisation
await captureManager.StopPreviewAsync();
//rend visible les composants
tfComment.Visibility = Visibility.Visible;
vbImgDisplay.Visibility = Visibility.Visible;
//Converti l'image en tableau de byte
photoByte = await GetByteFromFile(photoFile);
//Précise qu'on est plus en prévisualisation
EnPreview = false;
previewpicture.Label = "Prévisualiser";
}
}
//Converti un storageFile en Byte[]
private async Task<byte[]> GetByteFromFile(StorageFile storageFile)
{
var stream = await storageFile.OpenReadAsync();
using (var dataReader = new DataReader(stream))
{
var bytes = new byte[stream.Size];
await dataReader.LoadAsync((uint)stream.Size);
dataReader.ReadBytes(bytes);
return bytes;
}
}
Thx in advance for your help!
I'd suggest you to use the Lumia (Nokia) Imaging SDK to rotate the image, it's much easier.
You can get them here:
https://www.nuget.org/packages/LumiaImagingSDK/2.0.184
And you can rotate the image like this:
using (var filterEffect = new FilterEffect(source))
{
// Initialize the filter and add the filter to the FilterEffect collection to rotate for 15 degrees
var filter = new RotationFilter(15.0);
filterEffect.Filters = new IFilter[] { filter };
// Create a target where the filtered image will be rendered to
var target = new WriteableBitmap(width, height);
// Create a new renderer which outputs WriteableBitmaps
using (var renderer = new WriteableBitmapRenderer(filterEffect, target))
{
// Render the image with the filter(s)
await renderer.RenderAsync();
// Set the output image to Image control as a source
ImageControl.Source = target;
}
await SaveEffectAsync(filterEffect, "RotationFilter.jpg", outputImageSize);
}
//this method will rotate an image any degree
public static Bitmap RotateImage(Bitmap image, float angle)
{
//create a new empty bitmap to hold rotated image
double radius = Math.Sqrt(Math.Pow(image.Width, 2) + Math.Pow(image.Height, 2));
Bitmap returnBitmap = new Bitmap((int)radius, (int)radius);
//make a graphics object from the empty bitmap
using (Graphics graphic = Graphics.FromImage(returnBitmap))
{
//move rotation point to center of image
graphic.TranslateTransform((float)radius / 2, (float)radius / 2);
//rotate
graphic.RotateTransform(angle);
//move image back
graphic.TranslateTransform(-(float)image.Width / 2, -(float)image.Height / 2);
//draw passed in image onto graphics object
graphic.DrawImage(image, new Point(0, 0));
}
return returnBitmap;
}