I'm working on upgrading a site from CMS 11 to 12. It is landing on a blank page. It is not throwing any error. Don't know why epi returns a blank page.
Blank Page Content:Blankpage
It has to land on Start Page which is likely a homepage. I tried debugging the code ,but break point never hits StartPage Controller. Some where flow is breaking and never goes to controller, returns a blank page.
Here is my startup.cs
public class Startup
{
private readonly IWebHostEnvironment _webHostingEnvironment;
private readonly IConfiguration _configuration;
public Startup(IWebHostEnvironment webHostingEnvironment, IConfiguration configuration)
{
_webHostingEnvironment = webHostingEnvironment;
_configuration = configuration;
}
public void ConfigureServices(IServiceCollection services)
{
if (_webHostingEnvironment.IsDevelopment())
{
AppDomain.CurrentDomain.SetData("DataDirectory", Path.Combine(_webHostingEnvironment.ContentRootPath, "App_Data"));
services.Configure<SchedulerOptions>(options => options.Enabled = false);
}
services.AddApplicationInsightsTelemetry();
services.AddHttpContextAccessor();
services.AddMemoryCache();
services.AddResponseCaching();
services
//.AddCmsAspNetIdentity<ApplicationUser>()
.AddCms()
.AddAlloy() //Service collections Extensions
.AddFind()
//.AddAdminUserRegistration()
.AddEmbeddedLocalization<Startup>();
services.AddCors(opt =>
{
opt.AddPolicy(name: "CorsPolicy", builder =>
{
builder.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod();
});
});
services.AddContentDeliveryApi();
services.AddAlloyHideTabs();
// Required by Wangkanai.Detection to handle multiple devices
services.AddDetection();
services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromSeconds(10);
options.Cookie.HttpOnly = true;
options.Cookie.IsEssential = true;
});
services.Configure<CookiePolicyOptions>(options =>
{
options.MinimumSameSitePolicy = SameSiteMode.Strict;
options.Secure = CookieSecurePolicy.Always;
options.HttpOnly = HttpOnlyPolicy.Always;
});
services.AddAuthentication(options =>
{
options.DefaultScheme = "okta.auth";
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie("okta.auth", options =>
{
options.Events.OnSignedIn = async ctx =>
{
if (ctx.Principal?.Identity is ClaimsIdentity claimsIdentity)
{
// Syncs user and roles so they are available to the CMS
var synchronizingUserService = ctx
.HttpContext
.RequestServices
.GetRequiredService<ISynchronizingUserService>();
await synchronizingUserService.SynchronizeAsync(claimsIdentity);
}
};
})
.AddOpenIdConnect(options =>
{
options.SignInScheme = "okta.auth";
options.SignOutScheme = "okta.auth";
options.ClientId = _configuration["Okta:ClientId"];
options.ClientSecret = _configuration["Okta:ClientSecret"];
options.Authority = _configuration["Okta:Authority"];
options.SignedOutCallbackPath = _configuration["Okta:PostLogoutRedirectUrl"];
options.CallbackPath = "/signin-oidc";
options.Scope.Add(_configuration["Okta:Scopes"]);
options.ResponseType = "code";
options.SaveTokens = true;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = false,
NameClaimType = "name",
RoleClaimType = "groups"
};
options.Events = new OpenIdConnectEvents
{
OnAuthenticationFailed = async context =>
{
var contentLoader = ServiceLocator.Current.GetInstance<IContentLoader>();
var urlResolver = ServiceLocator.Current.GetInstance<UrlResolver>();
var startPage = contentLoader.Get<StartPage>(ContentReference.StartPage);
if (context.Request.Path.Value != null && !context.Request.Path.Value.ToLower().Contains("episerver"))
{
context.Response.Redirect($"{startPage.LoginPage.GetPublicUrl().TrimEnd('/')}?returnUrl={Uri.EscapeDataString(context.Request.GetEncodedUrl())}");
context.HandleResponse();
}
if (ContentReference.StartPage.ID != 0 && context.Exception.Message.Contains("User is not assigned to the client application"))
{
context.Response.Redirect($"{urlResolver.GetUrl(startPage.LoginPage)}?loginErrorMessage={Uri.EscapeDataString("User is not assigned to the client application. Make sure the user is assigned to the application or to a group assigned to the application in Okta.")}");
context.HandleResponse();
}
else
{
await context.Response.WriteAsync(context.Exception.Message);
context.HandleResponse();
}
await Task.CompletedTask;
},
OnRedirectToIdentityProvider = async context =>
{
if (context.Response.StatusCode == 401)
{
context.HandleResponse();
}
// If signing out, add the id_token_hint
if (context.ProtocolMessage.RequestType == OpenIdConnectRequestType.Logout)
{
var idTokenHint = context.HttpContext.User.FindFirst(OpenIdConnectParameterNames.IdToken);
if (idTokenHint != null)
{
context.ProtocolMessage.IdTokenHint = idTokenHint.Value;
}
context.HandleResponse();
await Task.CompletedTask;
return;
}
var contentLoader = context.HttpContext.RequestServices.GetRequiredService<IContentLoader>();
if (ContentReference.StartPage.ID != 0)
{
var startPage = contentLoader.Get<StartPage>(ContentReference.StartPage);
var loginPageUrl = startPage.LoginPage.GetPublicUrl();
if (!context.HttpContext.Request.Path.Value.ToLower().Contains("episerver") && startPage.LoginPage == null)
{
context.HttpContext.Response.StatusCode = 404;
context.HandleResponse();
return;
}
if (!context.HttpContext.Request.Path.Value.ToLower().Contains("episerver") && context.HttpContext.Request.Cookies["Epi-Auth-Flow"] == null)
{
context.HttpContext.Response.Redirect($"{loginPageUrl.TrimEnd('/')}?returnUrl={Uri.EscapeDataString(context.HttpContext.Request.GetEncodedUrl())}");
context.HandleResponse();
return;
}
}
HandleMultiSiteReturnUrl(context);
if (context.HttpContext.Response.StatusCode == 401 && context.HttpContext.User.Identity.IsAuthenticated)
{
context.HttpContext.Response.StatusCode = 403;
context.HandleResponse();
return;
}
if (context.HttpContext.Response.StatusCode == 401 && IsXhrRequest(context.HttpContext.Request))
{
context.HandleResponse();
return;
}
//context.HandleResponse();
await Task.CompletedTask;
},
OnAuthorizationCodeReceived = context =>
{
// Handle authorization code received
return Task.CompletedTask;
},
OnTokenValidated = (ctx) =>
{
var redirectUri = new Uri(ctx.Properties.RedirectUri, UriKind.RelativeOrAbsolute);
if (redirectUri.IsAbsoluteUri)
{
ctx.Properties.RedirectUri = redirectUri.PathAndQuery;
}
//// Sync user and the roles to EPiServer in the background
//var synchronizingUserService = ctx.HttpContext.RequestServices.GetRequiredService<ISynchronizingUserService>();
return Task.CompletedTask;
}
};
});
services.AddHttpContextAccessor();
services.AddMemoryCache();
services.AddTransient<IOktaServices>(serviceProvider => new OktaServices(serviceProvider.GetService<IConfiguration>()!));
services.AddControllersWithViews();
services.AddMvc(options =>
{
options.CacheProfiles.Add("PageControllerBaseOutputCacheProfile", new CacheProfile
{
Duration = 0, // Cache duration in seconds. Set to 0 for no caching.
Location = ResponseCacheLocation.None,
NoStore = true
});
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
// Required by Wangkanai.Detection
app.UseDetection();
app.UseSession();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapRazorPages();
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
endpoints.MapControllers();
endpoints.MapRazorPages();
endpoints.MapContent();
});
// Map the "/util/logout.aspx" endpoint
app.Map("/util/logout", map =>
{
map.Run(async context =>
{
// Sign out the user
await context.SignOutAsync();
if (ContentReference.StartPage.ID == 0)
{
return;
}
var contentLoader = context.RequestServices.GetRequiredService<IContentLoader>();
var urlResolver = context.RequestServices.GetRequiredService<UrlResolver>();
var startPage = contentLoader.Get<StartPage>(ContentReference.StartPage);
// Redirect to the start page
context.Response.Redirect(
$"{context.Request.Scheme}://{context.Request.Host}{urlResolver.GetUrl(startPage)}");
});
});
}
public void ConfigureContainer(ServiceCollection context)
{
//Register custom implementations that should be used in favor of the default implementations
context.AddTransient<IContentRenderer, ErrorHandlingContentRenderer>()
.AddTransient<ContentAreaRenderer, AlloyContentAreaRenderer>()
.AddTransient<IMessageSender, SmtpSender>();
}
private static bool IsXhrRequest(HttpRequest request)
{
const string xRequestedWith = "X-Requested-With";
var query = request.Query;
if (query.ContainsKey(xRequestedWith) && query[xRequestedWith] == "XMLHttpRequest")
{
return true;
}
var headers = request.Headers;
return headers.ContainsKey(xRequestedWith) && headers[xRequestedWith] == "XMLHttpRequest";
}
private void HandleMultiSiteReturnUrl(RedirectContext context)
{
if (context.ProtocolMessage.RedirectUri == null)
{
var currentUrl = context.HttpContext.Request.GetEncodedUrl();
context.ProtocolMessage.RedirectUri = currentUrl;
}
}
}
Here is my ServiceCollection Class
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddAlloy(this IServiceCollection services)
{
services.Configure<RazorViewEngineOptions>(options => options.ViewLocationExpanders.Add(new SiteViewEngineLocationExpander()));
services.Configure<TinyMceConfiguration>(config =>
{
config.Default().AddSetting("extended_valid_elements",
"iframe[src|alt|title|width|height|align|name],picture,source[srcset|media],span")
.AddPlugin(
"epi-link epi-image-editor epi-dnd-processor epi-personalized-content print preview searchreplace autolink directionality visualblocks visualchars fullscreen image link media template codesample table charmap hr pagebreak nonbreaking anchor toc insertdatetime advlist lists textcolor " +
"wordcount imagetools contextmenu colorpicker textpattern help code")
.Toolbar(
"bold italic strikethrough forecolor | epi-link image epi-image-editor epi-personalized-content | imagevault-insert-media imagevault-edit-media | bullist numlist | searchreplace fullscreen ",
"styleselect formatselect | alignleft aligncenter alignright alignjustify | removeformat | table toc | code"
, "")
.Menubar("edit insert view format table tools help")
.BodyClass("main-content-wrapper")
.AddSetting("image_title", false)
.AddSetting("image_dimensions", true);
});
services.AddTinyMceSpellChecker();
services.Configure<DisplayOptions>(displayOption =>
{
displayOption.Add("full", "/displayoptions/full", Global.ContentAreaTags.FullWidth, string.Empty, "epi-icon__layout--full");
displayOption.Add("wide", "/displayoptions/wide", Global.ContentAreaTags.TwoThirdsWidth, string.Empty, "epi-icon__layout--two-thirds");
displayOption.Add("half", "/displayoptions/half", Global.ContentAreaTags.HalfWidth, string.Empty, "epi-icon__layout--half");
displayOption.Add("narrow", "/displayoptions/narrow", Global.ContentAreaTags.OneThirdWidth, string.Empty, "epi-icon__layout--one-third");
});
services.Configure<MvcOptions>(options => options.Filters.Add<PageContextActionFilter>());
services.AddDisplayResolutions();
services.AddDetection();
return services;
}
private static void AddDisplayResolutions(this IServiceCollection services)
{
services.AddSingleton<StandardResolution>();
services.AddSingleton<IpadHorizontalResolution>();
services.AddSingleton<IphoneVerticalResolution>();
services.AddSingleton<AndroidVerticalResolution>();
}
}