Hi @aaron, device language is being used by zero startup template. I've used it in the same way. As an example, DatetimeConverter is using it to format dates into strings... and that's completely fine to me. You have also some local strings in the startup template like "no internet connection" message that has nothing to do in server side.
So, for me, it is handy to have such possibility...and will not remove it from my project.
Therfore, having local translations in sync with selected user language seems to me obvious.
Hi @dfielec,
I'm also interested to add UWP support to Xamarin Form project. I have a good experience on Windows 10 development with UWP and the benefits of using windows store apps (Line Of Buisness apps can be deliver very easily to a dedicated company)
Did you overcome your last issue ? Do you have some display artefacts or lantencies in comparison to android or ios apps ?
Tks in advance.
Tks @alper for this detailed answer & tests. On my side, I was testing by toggling on cellular network button from android emulator...I will test with Wifi button to see if same issue is raised.
On other hand, I realized that on real android device, I did not have this timeout issue with same ode ! (just one time with an old android tablet).
I will test by adding a small delay and give a feedback
tks @alper
I already tried it before creating this issue. I've tried again right now by ignoring WebRequestExecuter
.
I still have the same exception (App is closed brutaly because exception is not being managed).
The same API call from a viewmodel command (fired by a button on a view) works like a charm. I really think that it's a threading issue but cannot find where to fix this.
This API call is firing an exception only after receiving a CrossConnectivity.Current.ConnectivityChanged event...
Here is the detailed exception :
Unhandled Exception: Flurl.Http.FlurlHttpTimeoutException: Call timed out: PUT https://myapp.com/api/services/app/Event/UpdateEventEdit
02-20 08:47:17.035 I/MonoDroid(23999): UNHANDLED EXCEPTION:
Thread started: <Thread Pool> #19
02-20 08:47:17.055 I/MonoDroid(23999): Flurl.Http.FlurlHttpTimeoutException: Call timed out: PUT https://my-app.com/api/services/app/Event/UpdateEventEdit ---> System.OperationCanceledException: The operation was canceled.
02-20 08:47:17.055 I/MonoDroid(23999): at ModernHttpClient.NativeMessageHandler+<SendAsync>c__async0.MoveNext () [0x00422] in /Users/paul/code/paulcbetts/modernhttpclient/src/ModernHttpClient/Android/OkHttpNetworkHandler.cs:132
02-20 08:47:17.055 I/MonoDroid(23999): --- End of stack trace from previous location where exception was thrown ---
02-20 08:47:17.055 I/MonoDroid(23999): at System.Net.Http.HttpClient+<SendAsyncWorker>d__49.MoveNext () [0x000ca] in <25ebe1083eaf4329b5adfdd5bbb7aa57>:0
02-20 08:47:17.055 I/MonoDroid(23999): --- End of stack trace from previous location where exception was thrown ---
02-20 08:47:17.055 I/MonoDroid(23999): at Flurl.Http.FlurlRequest+<SendAsync>d__19.MoveNext () [0x0029e] in <c38761af4558433f81b1691eb86a1548>:0
02-20 08:47:17.055 I/MonoDroid(23999): --- End of inner exception stack trace ---
02-20 08:47:17.055 I/MonoDroid(23999): at Flurl.Http.FlurlRequest+<HandleExceptionAsync>d__23.MoveNext () [0x000f7] in <c38761af4558433f81b1691eb86a1548>:0
02-20 08:47:17.055 I/MonoDroid(23999): --- End of stack trace from previous location where exception was thrown ---
02-20 08:47:17.055 I/MonoDroid(23999): at Flurl.Http.FlurlRequest+<SendAsync>d__19.MoveNext () [0x0037d] in <c38761af4558433f81b1691eb86a1548>:0
02-20 08:47:17.055 I/MonoDroid(23999): --- End of stack trace from previous location where exception was thrown ---
02-20 08:47:17.055 I/MonoDroid(23999): at Flurl.Http.FlurlRequest+<SendAsync>d__19.MoveNext () [0x00486] in <c38761af4558433f81b1691eb86a1548>:0
02-20 08:47:17.055 I/MonoDroid(23999): --- End of stack trace from previous location where exception was thrown ---
02-20 08:47:17.055 I/MonoDroid(23999): at Flurl.Http.HttpResponseMessageExtensions+<ReceiveJson>d__01[T].MoveNext () [0x0006e] in <c38761af4558433f81b1691eb86a1548>:0 02-20 08:47:17.055 I/MonoDroid(23999): --- End of stack trace from previous location where exception was thrown --- 02-20 08:47:17.055 I/MonoDroid(23999): at ApiClient.AbpApiClient+<PutAsync>d__41
1[T].MoveNext () [0x00089] in C:\Users\Ricardo Lopes\source\repos\AspnetZero2\aspnet-core\src\Application.Client\ApiClient\AbpApiClient.cs:354
02-20 08:47:17.055 I/MonoDroid(23999): --- End of stack trace from previous location where exception was thrown ---
02-20 08:47:17.055 I/MonoDroid(23999): at ApiClient.AbpApiClient+<PutAsync>d__39`1[T].MoveNext () [0x000c7] in C:\Users\Ricardo Lopes\source\repos\AspnetZero2\aspnet-core\src\Application.Client\ApiClient\AbpApiClient.cs:337
02-20 08:47:17.055 I/MonoDroid(23999): --- End of stack trace from previous location where exception was thrown ---
02-20 08:47:17.055 I/MonoDroid(23999): at Events.ProxyEventAppService+
Tks @ismcagdas.
I've read the documentation but I'm not sure : do you mean that injecting AbpSession will automatically set the tenant/user default culture inside the using block ?
Access to tenant/user settings can also be done in this way within a background worker ?
BTW, I've used CultureHelper class (like it is ised on useremailer class) to format date strings within background workers.
tks @Ismcagdas.
Thnaks to your links and other google search, I found the way : you just need to add an appsettings to the staging slot. Appsetting name must be : ASPNETCORE_ENVIRONMENT and value must be : Staging
This makes swaping slots much more safer.
I have now another issue on angular side for appconfig.json :
Therefore, when swaping slots, I still have to change manually appconfig.production.json (because remoteServiceBaseUrl and appBaseUrl are different)
Do you have a tip avoid this manual change ?
It's working now ! Thank you @maliming
this code is already there
I removed line
options.IndexStream = () => Assembly.GetExecutingAssembly() .GetManifestResourceStream("ELEVEN_SOFT.Myapp.Web.wwwroot.swagger.ui.index.html");
this makes swagger UI working again but I can't autenticate (tenant input is missing).
I've tried to change
.GetManifestResourceStream("ELEVEN_SOFT.Myapp.Web.wwwroot.swagger.ui.index.html");
by
.GetManifestResourceStream("ELEVEN_SOFT.Myapp.Web.Host.wwwroot.swagger.ui.index.html");
But I'm having same issue.
I've checked var names = Assembly.GetExecutingAssembly().GetManifestResourceNames().ToList();
: this returns no elements at all.
Any suggestion ?
Hi,
using System.IO;
using System;
using System.Linq;
using System.Reflection;
using Abp.AspNetCore;
using Abp.AspNetCore.SignalR.Hubs;
using Abp.AspNetZeroCore.Web.Authentication.JwtBearer;
using Abp.Castle.Logging.Log4Net;
using Abp.Dependency;
using Abp.Extensions;
using Abp.PlugIns;
using Abp.Timing;
using Castle.Facilities.Logging;
using Hangfire;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Cors.Internal;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using ELEVEN_SOFT.Myapp.Configuration;
using ELEVEN_SOFT.Myapp.EntityFrameworkCore;
using ELEVEN_SOFT.Myapp.Identity;
using ELEVEN_SOFT.Myapp.Web.Chat.SignalR;
using PaulMiami.AspNetCore.Mvc.Recaptcha;
using Swashbuckle.AspNetCore.Swagger;
using ELEVEN_SOFT.Myapp.Web.IdentityServer;
using ILoggerFactory = Microsoft.Extensions.Logging.ILoggerFactory;
namespace ELEVEN_SOFT.Myapp.Web.Startup
{
public class Startup
{
private const string DefaultCorsPolicyName = "localhost";
private readonly IConfigurationRoot _appConfiguration;
private readonly IHostingEnvironment _hostingEnvironment;
public Startup(IHostingEnvironment env)
{
_hostingEnvironment = env;
_appConfiguration = env.GetAppConfiguration();
}
public IServiceProvider ConfigureServices(IServiceCollection services)
{
//MVC
services.AddMvc(options =>
{
options.Filters.Add(new CorsAuthorizationFilterFactory(DefaultCorsPolicyName));
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_1); ;
services.AddSignalR(options => { options.EnableDetailedErrors = true; });
//Configure CORS for angular2 UI
services.AddCors(options =>
{
options.AddPolicy(DefaultCorsPolicyName, builder =>
{
//App:CorsOrigins in appsettings.json can contain more than one address with splitted by comma.
builder
.WithOrigins(
// App:CorsOrigins in appsettings.json can contain more than one address separated by comma.
_appConfiguration["App:CorsOrigins"]
.Split(",", StringSplitOptions.RemoveEmptyEntries)
.Select(o => o.RemovePostFix("/"))
.ToArray()
)
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
});
IdentityRegistrar.Register(services);
AuthConfigurer.Configure(services, _appConfiguration);
//Identity server
if (bool.Parse(_appConfiguration["IdentityServer:IsEnabled"]))
{
IdentityServerRegistrar.Register(services, _appConfiguration);
}
//Swagger - Enable this line and the related lines in Configure method to enable swagger UI
services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new Info { Title = "Myapp API", Version = "v1" });
options.DocInclusionPredicate((docName, description) => true);
//Note: This is just for showing Authorize button on the UI.
//Authorize button's behaviour is handled in wwwroot/swagger/ui/index.html
options.AddSecurityDefinition("Bearer", new BasicAuthScheme());
});
//Recaptcha
services.AddRecaptcha(new RecaptchaOptions
{
SiteKey = _appConfiguration["Recaptcha:SiteKey"],
SecretKey = _appConfiguration["Recaptcha:SecretKey"]
});
//Hangfire (Enable to use Hangfire instead of default job manager)
//services.AddHangfire(config =>
//{
// config.UseSqlServerStorage(_appConfiguration.GetConnectionString("Default"));
//});
//Configure Abp and Dependency Injection
return services.AddAbp<MyappWebHostModule>(options =>
{
//Configure Log4Net logging
options.IocManager.IocContainer.AddFacility<LoggingFacility>(
f => f.UseAbpLog4Net().WithConfig("log4net.config")
);
options.PlugInSources.AddFolder(Path.Combine(_hostingEnvironment.WebRootPath, "Plugins"), SearchOption.AllDirectories);
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
//Initializes ABP framework.
app.UseAbp(options =>
{
options.UseAbpRequestLocalization = false; //used below: UseAbpRequestLocalization
});
Clock.Provider = ClockProviders.Utc;
app.UseCors(DefaultCorsPolicyName); //Enable CORS!
app.UseAuthentication();
app.UseJwtTokenMiddleware();
if (bool.Parse(_appConfiguration["IdentityServer:IsEnabled"]))
{
app.UseJwtTokenMiddleware("IdentityBearer");
app.UseIdentityServer();
}
app.Use(async (context, next) =>
{
await next();
if (context.Response.StatusCode == 404 && !Path.HasExtension(context.Request.Path.Value))
{
context.Request.Path = "/index.html";
await next();
}
});
app.UseStaticFiles();
using (var scope = app.ApplicationServices.CreateScope())
{
if (scope.ServiceProvider.GetService<DatabaseCheckHelper>().Exist(_appConfiguration["ConnectionStrings:Default"]))
{
app.UseAbpRequestLocalization();
}
}
app.UseSignalR(routes =>
{
routes.MapHub<AbpCommonHub>("/signalr");
routes.MapHub<ChatHub>("/signalr-chat");
});
//Hangfire dashboard & server (Enable to use Hangfire instead of default job manager)
//app.UseHangfireDashboard("/hangfire", new DashboardOptions
//{
// Authorization = new[] { new AbpHangfireAuthorizationFilter(AppPermissions.Pages_Administration_HangfireDashboard) }
//});
//app.UseHangfireServer();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "defaultWithArea",
template: "{area}/{controller=Home}/{action=Index}/{id?}");
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
// Enable middleware to serve generated Swagger as a JSON endpoint
app.UseSwagger();
// Enable middleware to serve swagger-ui assets (HTML, JS, CSS etc.)
app.UseSwaggerUI(options =>
{
options.SwaggerEndpoint("/swagger/v1/swagger.json", "Myapp API V1");
options.IndexStream = () => Assembly.GetExecutingAssembly()
.GetManifestResourceStream("ELEVEN_SOFT.Myapp.Web.wwwroot.swagger.ui.index.html");
}); //URL: /swagger
}
}
}