Xamarin httpclient does not run more than once - c#

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;
}
}

Related

How can i handle JWT Tokens in my application

I'm a full time systems engineering student and i have a project that i've hit a bumped on the road, i'm handling right now all the users state with sessions and i would like to implement the JWT token for more "security", the application is a 2 part app (Api's = backend in one solution, Frontend in another solution)
Have to mention, I'm using C# in VS 2022 with asp.net .Net framework 4.7.2
The code architechture is MVC.
Here is my code
This is in the Users Model:
public string GetToken(Guid Id)
{
try
{
var key = ConfigurationManager.AppSettings["JwtKey"];
var issuer = ConfigurationManager.AppSettings["JwtIssuer"];
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key));
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
//Create a List of Claims, Keep claims name short
var permClaims = new List<Claim>();
permClaims.Add(new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()));
permClaims.Add(new Claim("userid", "Id"));
//Create Security Token object by giving required parameters
var token = new JwtSecurityToken(issuer, //Issure
issuer, //Audience
permClaims,
expires: DateTime.Now.AddDays(1),
signingCredentials: credentials);
var jwt_token = new JwtSecurityTokenHandler().WriteToken(token);
return jwt_token;
}
catch(Exception ex)
{
return string.Empty;
}
}
Once i get this token i include it in the Users object response and i'm able to see it in the front end response, i'm able to see the information being returned succesfully, I'm storing this data in a session variable.
this is my LogIn Controller:
[HttpPost]
public ActionResult ValidateUser(Users User)
{
if (User.noHashPass != null && User.Username != null)
{
var datos = model.ValidateUser(User);
var tok = datos.User;
if (datos != null)
{
Session["User"] = new Users();
Session["User"] = datos.User;
return RedirectToAction("Index", "Home");
}
else
{
return ViewBag.Msj = "¡ERROR! El usuario o la contraseña son incorrectos. Por favor intente de nuevo."; ;
}
}
else
{
ViewBag.Msj = "¡ERROR! El usuario o la contraseña son incorrectos. Por favor intente de nuevo.";
}
return View();
}
i was trying to do this to extract just the token piece in the users model:
public Respuesta ViewUserById(Guid Id)
{
using (var client = new HttpClient())
{
try
{
object sesion = new Users();
sesion = HttpContext.Current.Session["User"];
string api = "Users/ViewUserById?Id=" + Id;
string route = Url + api;
HttpResponseMessage response = client.GetAsync(route).Result;
response.EnsureSuccessStatusCode();
if (response.IsSuccessStatusCode)
{
var responseBody = response.Content.ReadAsAsync<Respuesta>().Result; //serializacion del obj JSON a un objeto
return responseBody;
}
else
{
throw new Exception("No se encontro un usuario existente bajo el Id:" + " " + Id);
}
}
catch (Exception ex)
{
throw ex;
}
}
}
But the sesion variable only gives me a ToString() function, i can see the sesion variable filling up and getting all the data but i cannot handle it for example, sesion.Token to get the Token inside the session variable.
Any suggestions are appreciated.
How can i handle the session variable in order to get the data within?

Angular requests to ASP.NET return "Error Unknown" when under SSL/TLS certificate

I've walked through this trouble and I've still didn't found any answer:
My Angular application sends a bunch of HTTP requests to asp.net. Asp.net process the request ( token check, etc.. ) and returns the data as ordered.
Thing is, on IIS, I've added SSL/TLS certificate from Let's Encrypt and the application never worked again.
Strange behaviours I've notivced
Only login method works. All request that follow, return "Unknown Error - Status Code 0"
Asp.net has an interceptor that filters every request to check the token. If I send the Authorization header, the application fails. If I don't, asp.net returns 404 error stating that token doesnt exists on the database ( as it shoud )
In Postman, the requests works 100% ( even the check of authenticity of the token)
If I remove either the angular interceptor and the middleware in asp.net AND remove the SSL cert. the application works
Chrome throws the "net::ERR_SPDY_PROTOCOL_ERROR" exception.
I've been over my head for two days and found no answer. Looked up on StackOverflow, IIS foruns, Angular foruns, .Net foruns... Nothing
Here some code:
Angular Interceptor
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
// Filtrar apenas pedidos feitos à API
if(req.url.match("\\api")) {
let newRequest = req.clone({
headers: new HttpHeaders({
'Content-Type':'application/json',
'Authorization':this.cookieService.get('at')
})
});
return next.handle(newRequest);
} else {
return next.handle(req);
}
}
Asp.NET Middleware
public Task Invoke(HttpContext context) {
// Check if request is redirected to ".../api/exemplo/xyx"
// To exclude the 'login' request
if (context.Request.Path.Value.StartsWith("/api")) {
// Check if request is NOT an OPTIONS
if(!context.Request.Method.Equals("OPTIONS")){
// Check for header
string auth = context.Request.Headers["Authorization"].ToString();
FbConnectionStringBuilder csb = new FbConnectionStringBuilder {
DataSource = _appSettings.DataSource,
Port = _appSettings.Port,
Database = _appSettings.Database,
UserID = _appSettings.UserID,
Password = _appSettings.Password,
ServerType = FbServerType.Default
};
// Open db
FbConnection db = new FbConnection(csb.ToString());
db.Open();
// Get the expiration date of token
string query = "SELECT DT_REVOG FROM ORGANIG_TOKEN WHERE TOKEN = #auth";
DateTime now = DateTime.UtcNow;
DateTime DateRevogToken;
try
{
DateRevogToken = db.QuerySingle<DateTime>(query, new { auth });
db.Close();
if (now >= DateRevogToken)
{
// Expired
string deleteQuery = "DELETE FROM ORGANIG_TOKEN WHERE TOKEN = #auth";
db.Execute(deleteQuery, new { auth });
context.Response.StatusCode = 401;
context.Response.WriteAsync("A token não é válida");
return Task.CompletedTask;
}
else
{
// Is valid
return _next(context);
}
} catch(Exception e) {
context.Response.StatusCode = 404;
context.Response.WriteAsync("Ocorreu um erro na verificação da token: " + e.Message);
return Task.CompletedTask;
}
}
else {
//It's a OPTIONS request. Ignore
return _next(context);
}
}
else {
// Login request. Ignore
return _next(context);
}
}
}
Login request (asp.net)
[Route("auth/gerar_token")]
[AllowAnonymous]
[HttpPost]
public async Task<IActionResult> GerarToken([FromBody] Client c)
{
// Conexão á base de dados Firebird
FbConnectionStringBuilder csb = new FbConnectionStringBuilder
{
DataSource = _appSettings.DataSource,
Port = _appSettings.Port,
Database = _appSettings.Database,
UserID = _appSettings.UserID,
Password = _appSettings.Password,
ServerType = FbServerType.Default
};
Client client = new Client();
string login = c.login;
string pass = c.pass;
string hashedPass = null;
string responseMessage;
// Hash da password do client
using (MD5 md5Hash = MD5.Create()) { hashedPass = GetMd5Hash(md5Hash, pass); }
using (var db = new FbConnection(csb.ToString())) {
string token;
try {
await db.OpenAsync();
// Query de login
string sql = #"SELECT CD, NOME, RAMO_ACT, DESIGN, EMAIL, LOGIN, MORAD
FROM ORGANIG WHERE LOGIN = #login AND PASS = #hashedPass";
client = await db.QuerySingleAsync<Client>(sql, new { login, hashedPass });
try {
int cd_organig = client.cd;
token = GenerateRefreshToken();
DateTime dt_cria = DateTime.UtcNow;
DateTime dt_revog = dt_cria.AddHours(4);
DateTime dt_inicio = DateTime.UtcNow;
string sql_token = #"INSERT INTO ORGANIG_TOKEN(TOKEN, CD_ORGANIG, DT_CRIA, DT_REVOG) VALUES (#token, #cd_organig, #dt_cria, #dt_revog)";
db.Execute(sql_token, new { token, cd_organig, dt_cria, dt_revog });
string sql_sessao = #"INSERT INTO ORGANIG_SESSAO(CD_ORGANIG, DT_INICIO, TOKEN, DT_REVOG_TOKEN) VALUES (#cd_organig, #dt_inicio, #token, #dt_revog)";
db.Execute(sql_sessao, new { cd_organig, dt_inicio, token, dt_revog });
}
catch (Exception e) {
JObject serverErroResponse = new JObject {
{ "Ocorreu um erro no servidor. Detalhes: ", e.Message }
};
db.Close();
return StatusCode(500, serverErroResponse);
}
JObject response = new JObject {
{ "token", token },
{ "cd", client.cd },
{ "nome", client.nome }
};
db.Close();
return Ok(response);
}
catch (Exception e) {
if(e.Message.Equals("Sequence contains no elements")) {
responseMessage = "Credenciais inválidas. Por favor, tente novamente";
} else {
responseMessage = "Ocorreu um erro no servidor. Detalhes: " + e.Message;
}
JObject serverErrorResponse = new JObject {
{ "message", responseMessage }
};
db.Close();
return StatusCode(500, serverErrorResponse);
}
} // using (var db = new FbConnection(csb.ToString()))
}
Example of request that doesnt work
[Route("api/build_organig/{cd}")]
[HttpGet]
public IActionResult BuildOrganig(int cd)
{
// Conexão á base de dados Firebird
FbConnectionStringBuilder csb = new FbConnectionStringBuilder {
DataSource = _appSettings.DataSource,
Port = _appSettings.Port,
Database = _appSettings.Database,
UserID = _appSettings.UserID,
Password = _appSettings.Password,
ServerType = FbServerType.Default
};
// Abrir conexão á base de dados
FbConnection db = new FbConnection(csb.ToString());
db.Open();
// Query para retornar os dados do procedure para uma lista
List<BuildOrganig> buildOrganigList = new List<BuildOrganig>();
buildOrganigList = db.Query<BuildOrganig>("SELECT CD, CD_BASE, NOME FROM BUILD_ORGANIG(#cd) ORDER BY NIVEL", new { cd }).ToList();
if (buildOrganigList.Count == 0) {
JObject emptyResponse = new JObject {
{ "count", buildOrganigList.Count },
{ "message", "Organigrama não existente" }
};
db.Close();
return StatusCode(404, emptyResponse);
}
db.Close();
return StatusCode(200, buildOrganigList);
}
Here are some screenshots of postman and the browser
If you need more info, just state in the comments.
Thanks
I had similar issues with Chrome and custom auth headers giving me a SPDY error.
I changed the name of my Authorization header to "X-Custom-Auth" and gave the OPTIONS a special response like this:
response.AddHeader("Access-Control-Allow-Methods", "GET, POST");
// Important: copy back the expected allowed headers
response.Headers["Access-Control-Allow-Headers"] = request.Headers["Access-Control-Request-Headers"];
response.AddHeader("Access-Control-Max-Age", "1728000");
response.Flush();
response.End();
You may also need to add your custom auth header name to web config or CORS config.
Hope it also applies in your case.

Exception lost after rethrow

I have a method ValidarConexaoEPI which validates a connection string trying to open a connection with it. In case of exceptions, the method who had call the "validate" one SolicitarNovaSincronizacao, catches it and rethrow a manipulated exception.
public static SincronizacaoSinc SolicitarNovaSincronizacao(int? idUsuario, int idAlmoxarifado, string versaoAplicacao, bool validaSincronizacaoEmAndatmento = true)
{
SincronizacaoSinc sincronizacaoSinc = null;
using (var conexaoLocal = new SqlConnectionEPI(_DbLocalConnectionString))
using (var conexaoServidor = new SqlConnectionEPI(_DbOnlineConnectionString))
{
sincronizacaoSinc = new SincronizacaoSinc(idUsuario, idAlmoxarifado, versaoAplicacao);
try
{
if (UtilDataAccess.ValidarConexaoEPI(conexaoLocal) && UtilDataAccess.ValidarConexaoEPI(conexaoServidor))
{
ValidarAlmoxarifadoBaseOnline(conexaoServidor, idAlmoxarifado);
ValidarUsuarioBaseOnline(conexaoServidor, idUsuario);
CriarRegistroSincronizacao(conexaoLocal, conexaoServidor, sincronizacaoSinc);
if(validaSincronizacaoEmAndatmento)
{
SolicitarSincronizacao(conexaoServidor, sincronizacaoSinc);
}
AtualizarRegistroSincronizacao(conexaoLocal, conexaoServidor, sincronizacaoSinc);
}
conexaoServidor.SqlTransaction.Commit();
conexaoLocal.SqlTransaction.Commit();
}
catch (Exception exception)
{
throw new Exception(String.Format(
"Erro ao iniciar sincronizacao. {0}", exception.Message), exception.InnerException);
}
}
return sincronizacaoSinc;
}
public static bool ValidarConexaoEPI(SqlConnectionEPI conexao) //This method is in another static class
{
try
{
conexao.Open();
}
catch (SqlException sqlException)
{
var dataSource = conexao != null && conexao.SqlConnection != null
? conexao.SqlConnection.DataSource : "string de conexão inválida";
throw new Exception(String.Format(
"Não foi possível estabelecer uma conexão com o banco de dados ({0}).", dataSource), sqlException);
}
catch (Exception exception)
{
throw new Exception(String.Format(
"Não foi possível estabelecer uma conexão com o banco de dados: {0}", exception.Message), exception);
}
return true;
}
But, after rethrow I lost the exception data. The next method, the one who called the SolicitarNovaSincronizacao() receive a NullReference exception. As you can see:
Exception catch on ValidarConexaoEPI():
NullReference exception catch:
Every other exception catch by SolicitarNovaSincronizacao is ok, the problem occur just with this one. The exception used to mount the new one is ok.
PS.: I know that it is not the right use of try/catch! Not my code.
EDIT:
Here is the StackTrace of the NullReferenceException:
em AG.ControleEPI.Dados.SqlConnectionEPI.Dispose() na C:\Projetos\AG\TFS2013\ControleEPI\Main\Source-locais\AG.ControleEPI.Dados\ADO\SqlConnectionEPI.cs:linha 28
em AG.ControleEPI.Dados.ADO.SincronizacaoDataAccess.SolicitarNovaSincronizacao(Nullable`1 idUsuario, Int32 idAlmoxarifado, String versaoAplicacao, Boolean validaSincronizacaoEmAndatmento) na C:\Projetos\AG\TFS2013\ControleEPI\Main\Source-locais\AG.ControleEPI.Dados\ADO\SincronizacaoOnline\SincronizacaoDataAccess.cs:linha 50
em AG.ControleEPI.Negocio.Gerenciador.SincronizacaoGerenciador.IniciarSincronizacao(Int32 idUsuario, Int32 idAlmoxarifado, String versaoAplicacao) na C:\Projetos\AG\TFS2013\ControleEPI\Main\Source-locais\AG.ControleEPI.Negocio\GerenciadorCustomizado\SincronizacaoGerenciador.cs:linha 84

Azure Servicebus Topic continuos Receiver message stops

I builded a Azure Service Bus Message provider to run in linux CENTOS 7 with core 2.0. I'm using the packge "Microsoft.Azure.ServiceBus 3.1.0". But when I receive
five hundred thousand(500 000) or more messages, the "RegisterMessageHandler" stop even with many active messages to read, does't receive anymore. I have five threads, "MaxConcurrentCall" with one hundred, Prefechcount 100 and "MaxAutoRenewDuration" in five minutes.
This method use "RegisterMessageHandler" to keep reading subscription continuously.
public async Task RecebeMensagemAsync(CancellationToken cancellationToken, Action<string> tratarObjetoImportado, int prefetchCount)
{
try
{
var receiver = new Microsoft.Azure.ServiceBus.SubscriptionClient(_serviceBusConnString, _topic, _subscription, this._receiveMode, new RetryExponential(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(10), _retryPolicyMaximumRetryCount));
receiver.PrefetchCount = prefetchCount;
receiver.OperationTimeout = TimeSpan.FromMinutes(_timoutOperacao);
var cicloRecebimentoCompleto = new TaskCompletionSource<bool>();
// fecha receiver e factory quando o CancellationToken é acionado
cancellationToken.Register(
async () =>
{
await receiver.CloseAsync();
cicloRecebimentoCompleto.SetResult(true);
});
// registra o RegisterMessageHandler para tratar mensagem lida assincronamente
receiver.RegisterMessageHandler(
async (message, cancellationTokenResponse) =>
{
if (message.Body == null || message.Body.Length == 0)
{
GerenciadorLog.LogInfo($"Mensagem não possui conteudo, mensageId: {message.MessageId}", LogType.Warning);
await receiver.CompleteAsync(message.SystemProperties.LockToken);
}
else
{
try
{
tratarObjetoImportado(Encoding.UTF8.GetString(message.Body));
if (_receiveMode == ReceiveMode.PeekLock)
await receiver.CompleteAsync(message.SystemProperties.LockToken);
}
catch (MessageSizeExceededException ex) {
GerenciadorLog.LogError($"Tamanho da mensagem:{message.MessageId}", ex);
try
{
if (_receiveMode == ReceiveMode.PeekLock)
await receiver.DeadLetterAsync(message.SystemProperties.LockToken);
}
catch (Exception dlex)
{
GerenciadorLog.LogError($"Erro ao enviar mensagem para 'DeadLetter', mensageId: {message.MessageId}", dlex);
throw new Exception("Erro não identificado", dlex);
}
}
catch (MessageLockLostException ex)
{
GerenciadorLog.LogError($"Expirou tempo de leitura da mensagem, será enviada para DeadLetter:{message.MessageId}", ex);
try
{
await receiver.AbandonAsync(message.SystemProperties.LockToken);
}
catch (Exception ex2)
{
GerenciadorLog.LogError($"Erro ao abandonar mensagem, mensageId:{message.MessageId}", ex2);
await Task.CompletedTask;
}
}
catch (MessagingEntityNotFoundException ex)
{
GerenciadorLog.LogError($"Mensagem não encontrada, mensageId:{message.MessageId}", ex);
try
{
await receiver.AbandonAsync(message.SystemProperties.LockToken);
}
catch (Exception ex2)
{
GerenciadorLog.LogError($"Erro ao abandonar mensagem, mensageId:{message.MessageId}", ex2);
await Task.CompletedTask;
}
}
catch (Exception ex)
{
if (ex != null && !string.IsNullOrEmpty(ex.Message))
GerenciadorLog.LogError($"Erro na importação, mensageId:{message.MessageId}", ex);
try
{
if (_receiveMode == ReceiveMode.PeekLock)
await receiver.DeadLetterAsync(message.SystemProperties.LockToken);
}
catch (Exception dlex)
{
GerenciadorLog.LogError($"Erro ao enviar mensagem para 'DeadLetter', mensageId: {message.MessageId}", dlex);
await Task.CompletedTask;
}
}
}
},
new MessageHandlerOptions((e) => LogMessageHandlerException(e, receiver)) { AutoComplete = false, MaxConcurrentCalls = _maxConcurrentCalls, MaxAutoRenewDuration = TimeSpan.FromSeconds(_lockDuration) });
await cicloRecebimentoCompleto.Task;
}
catch (Exception ex)
{
GerenciadorLog.LogError("Erro ao configurar 'listener' para leitura das mensagens.");
GerenciadorLog.LogError(ex.Message, ex);
throw ex;
}
}
And this method keep await the task. Can have more than one thread calling this method
public async Task Run(int segundosIntnervaloSondaConsultaTopico, int prefetchCount, Action<string> tratarObjetoImportado)
{
IList<CancellationTokenSource> cancellationTokensSource = new List<CancellationTokenSource>();
IList<Task> instanciasDasSondas = new List<Task>();
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
GerenciadorLog.LogInfo($"start blablalbala --");
var recebeMensagemAsync = RecebeMensagemAsync(cancellationTokenSource.Token, tratarObjetoImportado, prefetchCount);
await Task.WhenAll(Task.Run(() => Console.ReadKey()),
Task.Delay(TimeSpan.FromSeconds(segundosIntnervaloSondaConsultaTopico)).ContinueWith((t) => cancellationTokenSource),
Task.WhenAll(new Task[] { recebeMensagemAsync }));
}
Somebody knows the correct way to keep running or renew the client of register, or another approach?
It was fixed after update to "Microsoft.Azure.ServiceBus 3.1.1" package:
https://www.nuget.org/packages/Microsoft.Azure.ServiceBus/
tks.

Rotate a BitmapImage in c#

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;
}

Categories

Resources