Passing request parameters to ResourceHandler - servlets

I have a ServletContextHandler:
public class MyHandler extends ServletContextHandler {
public MyHandler() throws URISyntaxException, MalformedURLException {
setContextPath("/path");
ResourceHandler resourceHandler = new ResourceHandler();
resourceHandler.setDirectoriesListed(true);
resourceHandler.setWelcomeFiles(new String[]{ "index.jsp" });
URL resource = SwiftSocialMessenger.class.getClassLoader().getResource("resource");
resourceHandler.setBaseResource(Resource.newResource(resource.toURI().normalize()));
HandlerList handlers = new HandlerList();
handlers.setHandlers(new Handler[] { resourceHandler });
this.setHandler(handlers);
}
}
I need the request parameters in index.jsp page for example:
<html>
.....
<body>
<span title=<%= request.getParameter("param") %> </span>
</body>
<html>
Is it possible to get the request parameter using Resource Handler?

Related

How can i call servlet on button click aem

i have servlet
#Component(service={Servlet.class},
property={"sling.servlet.methods=get",
"sling.servlet.resourceTypes=/content/wknd-events"})
public class MainServlet extends SlingAllMethodsServlet
{
#Reference
DemoInterfaceImpl demoInterface;
protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException {
demoInterface.redirectUser(request,response);
}
}
demoInterface
#Component(
service= IDemoInterface.class,
immediate = true)
public class DemoInterfaceImpl implements IDemoInterface {
#Override
public void redirectUser(final SlingHttpServletRequest req,
final SlingHttpServletResponse resp) throws IOException {
resp.sendRedirect("/content/we-retail/us/en.html");
}
}
and i have my component
<a href="/content/wknd-events.html">
<button> go</button>
</a>
i want to redirect to /content/we-retail/us/en.html on button click but it doesn't work. I still go to /content/wknd-events.html. I don't understand where is my mistake
Your basic mistake is here "sling.servlet.resourceTypes=/content/wknd-events"})
The resourceType in Sling is the resourceType property set on the resources/nodes. So, if you register a servlet based on resourceType, it will get invoked only if you have the component or resource of that type. In your case , the servlet is registered with a content path as resourceType . Instead of sling.servlet.resourceTypes ; you can try sling.servlet.paths (e.g "sling.servlet.paths=/bin/test") and register your servlet to a path. Instead of giving a href attribute in the <a> tag, write an AJAX call on the click event of the button and give the servlet path as the URL.
$.ajax({
type: 'GET',
url:'/bin/test',
success: function(msg){
<!-- some code -->
}
});

How to implement pre-rendering in Blazor WASM

Blazor WASM with Prerendering gives error when clicking on Sign In link.
I added the following in Startup.cs:
services.AddScoped<AuthenticationStateProvider, ServerAuthenticationStateProvider>();
services.AddScoped<SignOutSessionStateManager>();
https://github.com/jonasarcangel/PrerenderWithAuth/blob/master/PrerenderWithAuth/Server/Startup.cs
This was suggested in https://github.com/dotnet/aspnetcore/issues/15253. Other changes were also taken from https://jonhilton.net/blazor-wasm-prerendering/.
This is the error:
System.InvalidCastException: Unable to cast object of type
'Microsoft.AspNetCore.Components.Server.ServerAuthenticationStateProvider'
to type
'Microsoft.AspNetCore.Components.WebAssembly.Authentication.IRemoteAuthenticationService`1[Microsoft.AspNetCore.Components.WebAssembly.Authentication.RemoteAuthenticationState]'.
UPDATE: I'm trying this, but I don't know what to put within each implementation.
public class HybridAuthenticationStateProvider : ServerAuthenticationStateProvider, IRemoteAuthenticationService<RemoteAuthenticationState>
{
public async Task<RemoteAuthenticationResult<RemoteAuthenticationState>> CompleteSignInAsync(RemoteAuthenticationContext<RemoteAuthenticationState> context)
{
throw new NotImplementedException();
}
public async Task<RemoteAuthenticationResult<RemoteAuthenticationState>> CompleteSignOutAsync(RemoteAuthenticationContext<RemoteAuthenticationState> context)
{
throw new NotImplementedException();
}
public async Task<RemoteAuthenticationResult<RemoteAuthenticationState>> SignInAsync(RemoteAuthenticationContext<RemoteAuthenticationState> context)
{
throw new NotImplementedException();
}
public async Task<RemoteAuthenticationResult<RemoteAuthenticationState>> SignOutAsync(RemoteAuthenticationContext<RemoteAuthenticationState> context)
{
throw new NotImplementedException();
}
}
Client Side
remove the wwwroot/index.html file
Program.Main
public static async Task Main(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("app");
builder.Services.AddHttpClient("PrerenderWithAuth.ServerAPI", client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress))
.AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();
// Supply HttpClient instances that include access tokens when making requests to the server project
builder.Services.AddScoped(sp => sp.GetRequiredService<IHttpClientFactory>().CreateClient("PrerenderWithAuth.ServerAPI"));
builder.Services.AddApiAuthorization();
await builder.Build().RunAsync();
}
Note this: builder.RootComponents.Add<App>("app");
"app" is without '#'
Server Side
Pages/_Host.cshtml
#page "/"
#namespace PrerenderWithAuth.Server.Pages
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>PrerenderWithAuth</title>
<base href="~/" />
<link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
<link href="css/app.css" rel="stylesheet" />
<link href="PrerenderWithAuth.Client.styles.css" rel="stylesheet" />
</head>
<body>
#*<div id="app">Loading...</div>*#
<app>
#if (!HttpContext.Request.Path.StartsWithSegments("/authentication"))
{
<component type="typeof(PrerenderWithAuth.Client.App)" render-mode="Static" />
}
else
{
<text>Loading...</text>
}
</app>
<div id="blazor-error-ui">
An unhandled error has occurred.
Reload
<a class="dismiss">🗙</a>
</div>
<script src="_content/Microsoft.AspNetCore.Components.WebAssembly.Authentication/AuthenticationService.js"></script>
<script src="_framework/blazor.webassembly.js"></script>
</body>
</html>
PrerenderWithAuth.Server/_Imports.razor
#using System.Net.Http
#using Microsoft.AspNetCore.Authorization
#using Microsoft.AspNetCore.Components.Authorization
#using Microsoft.AspNetCore.Components.Forms
#using Microsoft.AspNetCore.Components.Routing
#using Microsoft.AspNetCore.Components.Web
#using Microsoft.JSInterop
#using PrerenderWithAuth
#using PrerenderWithAuth.Shared
Startup class:
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Components.Server;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.ResponseCompression;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using PrerenderWithAuth.Server.Data;
using PrerenderWithAuth.Server.Models;
using System.Linq;
namespace PrerenderWithAuth.Server
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
// Added by me
services.Configure<RazorPagesOptions>(options => options.RootDirectory = "/Pages");
// Added by me
services.AddScoped<AuthenticationStateProvider, ServerAuthenticationStateProvider>();
// Added by me
services.AddScoped<SignOutSessionStateManager>();
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDatabaseDeveloperPageExceptionFilter();
services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddIdentityServer()
.AddApiAuthorization<ApplicationUser, ApplicationDbContext>();
services.AddAuthentication()
.AddIdentityServerJwt();
services.AddControllersWithViews();
services.AddRazorPages();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseMigrationsEndPoint();
app.UseWebAssemblyDebugging();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseBlazorFrameworkFiles();
app.UseStaticFiles();
app.UseRouting();
app.UseIdentityServer();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
endpoints.MapControllers();
// endpoints.MapFallbackToFile("index.html");
endpoints.MapFallbackToPage("/_Host");
});
}
}
}

Appending Dynamic CSS to Static CSS File Content in MVC

I feel like I'm either really close on this, or miles away - MVC/Razor isn't yet in my wheelhouse. I've looked at too many "Dynamic CSS" links in SO and elsewhere to list.
I have a static CSS file (~/Content/site.css) that I want to add additional CSS classes to (in my case, based on data from a database).
I created the following:
public class CssController : Controller
{
private string GetCustomCss()
{
var builder = new StringBuilder();
var colorInfo = mRepository.GetColors();
foreach (var detail in colorInfo.ResultValue)
{
builder.Append(detail.CustomName);
builder.Append("-light-color");
builder.Append(" { ");
builder.Append("color: ");
GetLightColor(detail, builder);
builder.Append("; ");
builder.Append(" } ");
}
}
return builder.ToString();
}
public ContentResult DynamicCss()
{
var siteCss = string.Format("{0}{1}",
System.IO.File.ReadAllText(Server.MapPath("/Content/Site.css")),
GetCustomCss());
return Content(siteCss, "text/css");
}
}
And in my _Layout file:
<head>
<link href="#Url.Action("DynamicCss", "CssController")"
rel="stylesheet"
type="text/css" />
</head>
I guess I'd like to know what my bug is with this code, but if there is another "Best Practice" that you could point me to, I'd appreciate it.
I'm not sure if there is a best practice here, but one option may be an HttpHandler that reads that supplements an existing css file.
First, add a handler.
using System.Web;
namespace MyApp.Infrastructure
{
public class DynamicCss : IHttpHandler
{
public bool IsReusable {
get {
return true;
}
}
public void ProcessRequest(HttpContext context)
{
//original css file
var path = HttpContext.Current.Server.MapPath("~/Content/bootstrap.css");
HttpContext.Current.Response.ContentType = "text/css";
HttpContext.Current.Response.TransmitFile(path);
//Add other your custom components
HttpContext.Current.Response.Write(".other {color:blue}");
HttpContext.Current.Response.Flush();
}
}
}
Next, register the handler in the web.config.
<system.webServer>
<handlers>
<add name="dynamicCss" path="myCss.cssx" verb="*"
type="MyApp.Infrastructure.DynamicCss" />
</handlers>
</system.webServer>
Almost done. Make sure that MVC ignores the new cssx extension.
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.cssx"); //Added this line
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
Finally, link to it in the _layout
<link href="~/sitecss.cssx" rel="stylesheet" type="text/css"/>

SignalR hub hangs on IIS

We use SignalR library in our ASP.NET web application. The code looks as following:
Server:
[HubName("ticketsCounterHub")]
public class MassivePrintHub : Hub
{
public void PostTicketsCount(long count)
{
Clients.All.Send(count);
}
}
public class HubFactory
{
private HubFactory() {}
public static readonly HubFactory Current = new HubFactory();
public IHubProxy GetMassivePrintHubProxy()
{
var hubConnection = new HubConnection(ConfigUtils.GetRequiredSettingValue("adminPath"));
var hubProxy = hubConnection.CreateHubProxy("ticketsCounterHub");
hubConnection.Start().Wait();
return hubProxy;
}
}
Client (JavaScript):
MassivePrintApp.controller("ListController", function ($scope, Dates) {
var hubManager = (function () {
var massivePrintHub = $.connection.ticketsCounterHub;
$.connection.hub.start();
return { massivePrintHub: massivePrintHub };
} ());
hubManager.massivePrintHub.client.Send = function (ticketsCount) {
$scope.action.Quantity = ticketsCount;
$scope.$digest();
};
});
The key part of code is in MVC controller:
public FileResult PrintAction(int actionId, int count, DateTime actionDate, bool isThermo=false)
{
var ticketsCount = _ticketService.GetTicketsInStatusCount(actionId, actionDate, TicketStatusEnum.ToPrint);
HubFactory.Current.GetMassivePrintHubProxy().Invoke("PostTicketsCount", ticketsCount);
var stream = new MemoryStream();
xmlResponse.Save(stream);
stream.Flush();
stream.Position = 0;
return File(stream,ContentTypeEnum.XML.ToString(),String.Format("массовая {0} мероприятия {1} {2}шт.xml", isThermo?"термопечать":"печать", action.Artist,count));
}
As you can see, we have this line:
HubFactory.Current.GetMassivePrintHubProxy().Invoke("PostTicketsCount", ticketsCount);
And that causes the issue, that is whenever we call it one more instance of hub was added to "Requests" section on IIS.
I understand we already started hub in JavaScript code, but I'm not sure how can I use the existing connection or how to get rid of HubFactory or delete created hub instance.
And I don't understand why hub hangs on IIS.
Starting from a more simple example will help you a lot I guess. After that you can look into hosting your SignalR server differently (Console App or Windows Service) the basics won't change
(First installed SignalR: NuGet: install-package Microsoft.AspNet.SignalR)
I made a simple web-app example. The project has a Hub class:
using Microsoft.AspNet.SignalR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace SRTest
{
public class MassivePrintHub : Hub
{
private static IHubContext hubContext = GlobalHost.ConnectionManager.GetHubContext<MassivePrintHub>();
// Can be called from your Javascript code
public void PostTicketsCount(long count)
{
Clients.All.Send(count);
}
// Can be called from your c# code
public static void Static_PostTicketsCount(long count)
{
hubContext.Clients.All.Send(count);
}
}
}
An Owin startup class:
using Microsoft.AspNet.SignalR;
using Microsoft.Owin;
using Owin;
[assembly: OwinStartup(typeof(SRTest.Startup))]
namespace SRTest
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
var hubConfiguration = new HubConfiguration();
hubConfiguration.EnableDetailedErrors = true;
app.MapSignalR(hubConfiguration);
}
}
}
Page (Razor just to be able to call a simulator which calls a c# class to post message from backend):
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>TEST PAGE</title>
<!--Reference the jQuery library. -->
<script src='Scripts/jquery-1.6.4.js'></script>
<!--Reference the SignalR library. -->
<script src='Scripts/jquery.signalR-2.2.0.js'></script>
<!--Reference the autogenerated SignalR hub script. -->
<script src="signalr/hubs"></script>
</head>
<body>
THIS IS A TEST PAGE
<!-- Call simulator (trigger event every 5 seconds) -->
#{SRTest.SendFromBackEnd.SimulateSend();}
<script>
$(function () {
var printHub = $.connection.massivePrintHub;
// when send event happens
printHub.client.send = function (count) {
console.log("Send " + count + " tickets");
};
$.connection.hub.start().done(function () {
console.log("Connected");
});
$.connection.hub.logging = true;
});
</script>
</body>
</html>
And I added a dummy class which triggers the event through hubcontext every 5 seconds.
using System.Threading;
using System.Web;
namespace SRTest
{
public class SendFromBackEnd
{
public static void SimulateSend()
{
new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
while (true)
{
MassivePrintHub.Static_PostTicketsCount(2);
Thread.Sleep(5000);
}
}).Start();
}
}
}
I added some loggings to the SignalR, add some debug points, it will help you understand the basics, then it will be much easier to build what you are planning to build.
EDIT
About the hanging request: As long as you have a client connected to your SignalR server with SSE or AJAX Long-Polling, you will have an ongoing request, which never finishes. (In case of AJAX Long-polling, it finishes for very short times and comes back). In the apps where I use only Javascript clients, I only see the request if a page is open where I am listening to events. If no page or static page open then no request.
In the apps where I am using .NET clients, as long as the two apps are running, and both Sartup classes executed, the request will always be there, even if no page open. (Since the .NET client is still listening to events.)
For more info: http://hanselminutes.com/291/damian-edwards-explains-the-realtime-web-for-aspnet-with-signalr
This is a Threading related issue. Try like this
Task.Run(() => connection.Start().ContinueWith(task =>
{
.....
})).Wait();

SignalR client is not being connected

Here's my hub class:
public class ZaaloverzichtHub : Hub
{
IHubContext context = GlobalHost.ConnectionManager.GetHubContext<ZaaloverzichtHub>();
private static readonly Lazy<ZaaloverzichtHub> instance = new Lazy<ZaaloverzichtHub>(() => new ZaaloverzichtHub());
public static ZaaloverzichtHub Instance { get { return instance.Value; } }
public void Send()//PartialViewResult zaaloverzicht)
{
// Call the broadcastMessage method to update clients.
context.Clients.All.broadcastMessage("test");
}
}
And here's the javascript in my view:
$(function () {
var connection = $.connection.ZaaloverzichtHub;
connection.client.broadcastMessage = function (zaaloverzicht) {
window.alert(zaaloverzicht);
}
$.connection.hub.start();
});
I'm calling the Send() method from my controller
var hub = ZaaloverzichtHub.Instance;
hub.Send();
The Send() method in the hub is being called however nothing is happening on the client side. I know the client is not being connected to the hub because when i make a method like this:
public override System.Threading.Tasks.Task OnConnected()
{
return base.OnConnected();
}
And place a breakpoint, the breakpoint is never hit.
The convention for SignalR is to use a lowercase naming scheme on the client side unless explicitly named using an attribute in c#
var connection = $.connection.zaaloverzichtHub;//note the case change on Z to z

Resources