Razor Component event not firing in Razor Page - razor-pages

How do I get events to fire in a Razor component running in a Razor page?
My Startup:
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddServerSideBlazor();
}
// 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();
}
else
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
endpoints.MapBlazorHub();
});
}
My Razor Page calling the component:
#page
#model DocketDetail.OrderModel
#{
Layout = null;
}
#using RelationalObjectLayerCore;
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<script src="~/lib/jquery/dist/jquery.js"></script>
<link href="~/lib/bootstrap/dist/css/bootstrap.css" rel="stylesheet" />
<script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
<script src="_framework/blazor.server.js"></script>
<script src="~/js/site.js"></script>
<title>Order</title>
</head>
<body>
<component type="typeof(Component.Filedby)" render-mode="ServerPrerendered" />
</body>
Everything displays properly.
My component:
#using Microsoft.AspNetCore.Components
#code {
private void SearchPerson()
{
string x = "TEST";
}
}
<button #onclick="SearchPerson">Search</button>
Obviously this is pared down from my actual code... but I can not figure out how to get "SearchPerson" to fire in the Razor Component.

Found this:
https://learn.microsoft.com/en-us/aspnet/core/blazor/hosting-models?view=aspnetcore-3.1#integrate-razor-components-into-razor-pages-and-mvc-apps
With this little note:
Add a <script> tag for the blazor.server.js script inside of the
closing </body> tag:
HTML
<script src="_framework/blazor.server.js"></script>
Moved my script tag and it now works.
Thanks everyone for your suggestions.

I think I see what you're trying to do. Not sure if that is going to work they way you intend. The component will get rendered using Blazor, but the code attached to the button won't function. Put the #code{} for your button on the page that gets loaded. Or you can do an OnInitialized() overload if you want that code to run each time the page is loaded.
Also, make sure that the Blazor is rendering properly in the browser. Use F12 and make sure it says connected.
https://learn.microsoft.com/en-us/aspnet/core/blazor/lifecycle?view=aspnetcore-3.1

Related

Blazor WASM hosted project on IIS : 404 errors when DLL are loaded

My app is a blazor app, web assembly and hosted.
I installed IIS in windows, and added a site named PBM.
Then, I published my app with webassembly, here are some parameters:
(it says the deployment mode is framework dependant, and the target runtime is 'portable').
Here is the directory structure in IIS:
The errors I get are 404 while the app is loading, and especially when the DLL are loaded: (here is the debug windows of chrome)
The error of integrity seems as I read somewhere not the origin of the problem, its real origin is the 404 (not found) error.
I saw that there is no _framework directory in the PBM folder. Is this normal? There is one in wwwroot(is seems to be the one of the client project?. But there are DLL in the PBM folder:
Please notice I changed the index.html (usually located in the wwwroot directory of the client project)to index.cshtml (in the Pages directory of the Server project), in order to use multiple configurations.
Can you tell me how to fix these 404 errors with the DLLs?
thank you.
EDIT
#Lex Li: here is my web.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<location path="." inheritInChildApplications="false">
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath=".\Application.Server.exe" stdoutLogEnabled="true" stdoutLogFile=".\logs\stdout" hostingModel="inprocess" />
</system.webServer>
</location>
</configuration>
It seems there is no particular change to default file types.
EDIT
#Just the benno: here is my Startup.cs file:
public class Startup
{
public string ConnectionString { get; set; }
public Startup(IWebHostEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
Configuration = builder.Build();
}
public IConfiguration Configuration { get; set; }
// 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)
{
services.AddControllersWithViews();
services.AddRazorPages();
services.AddDbContext<DB>(options => {
options.UseSqlServer(Configuration.GetValue<string>("Configuration:Connection"));
});
services.AddScoped<DB>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
Tools.ConnectionString = Configuration.GetValue<string>("Configuration:Connection");
app.UsePathBase(Configuration.GetValue<string>("Configuration:AppBasePath"));
if (Configuration.GetValue<bool>("Configuration:IsProduction"))
{
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();
Console.WriteLine("prod");
}
else
{
app.UseDeveloperExceptionPage();
app.UseWebAssemblyDebugging();
Console.WriteLine("dév");
}
if (Configuration.GetValue<bool>("Configuration:IsProduction"))
app.UseBlazorFrameworkFiles("/PBM");
else
app.UseBlazorFrameworkFiles();
app.UseStaticFiles();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
endpoints.MapControllers();
endpoints.MapFallbackToPage("/BlazorApp");
});
}
}
For the DLL files's locations, I thought there were 2 DLL groups : one for the Server project(located in 'app folder'/_framework and the second one for the client project(located in 'app folder'/wwwroot/_framework.
(see here at microsoft.com :
The client Blazor WebAssembly app is published into the /bin/Release/{TARGET FRAMEWORK}/publish/wwwroot folder of the server app, along with any other static web assets of the server app. The two apps are deployed together.
My problem being that the DLLs of the server project aren't in the right place.
But I can make a mistake.
Here is the folders content:
'app root folder':
I can see Blazor.Canvas.dll, which is a dll of the client.
'wwwroot'/_framework:
EDIT:
BlazorApp is an alternative to index.html, because I couldn't inject the IConfiguration instance in index.html, so I use BlazorApp.cshtml instead. It is located in the server project, in the Pages directory.
Its content:
#page "/"
#using Microsoft.Extensions.Configuration
#using Microsoft.Extensions.Hosting
#inject Microsoft.AspNetCore.Hosting.IWebHostEnvironment HostingEnv
#inject IConfiguration Config
<!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>Application</title>
#if (Config.GetValue<bool>("Configuration:IsProduction"))
{
<h1>PROD</h1>
<base href="/PBM/" />
}
else
{
<h1>DEV</h1>
<base href="/" />
}
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" rel="stylesheet" />
<link href="_content/MudBlazor/MudBlazor.min.css" rel="stylesheet" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css">
<link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
<link href="css/app.css" rel="stylesheet" />
<script src="_framework/blazor.webassembly.js"></script>
<script src="js/AnchorLink.js"></script>
<script src="js/focus.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.9.4/dist/Chart.min.js"></script>
<!-- This is the glue between Blazor and Chart.js -->
<script src="_content/ChartJs.Blazor.Fork/ChartJsBlazorInterop.js"></script>
<!-- composant AnchorNavigation-->
<script>
function whitifyDashboardMenuItems() {
document.getElementById("syntheseMenu").classList.remove("active");
document.getElementById("patientsMenu").classList.remove("active");
document.getElementById("preopMenu").classList.remove("active");
document.getElementById("transfusionMenu").classList.remove("active");
document.getElementById("postopMenu").classList.remove("active");
document.getElementById("suiviJ30Menu").classList.remove("active");
document.getElementById("dmsMenu").classList.remove("active");
return 0;
}
function BlazorScrollToId(id) {
const element = document.getElementById(id);
if (element instanceof HTMLElement) {
element.scrollIntoView({
behavior: "smooth",
block: "start",
inline: "nearest"
});
}
}
function BlazorScrollDirectToId(id) {
const element = document.getElementById(id);
if (element instanceof HTMLElement) {
element.scrollIntoView({
behavior: "auto",
block: "start",
inline: "nearest"
});
}
}
function changeMenuAfterStartup() {
const dms = document.getElementById("dmsMenu");
if (dms instanceof HTMLElement)
dms.classList.remove("active");
const synthese = document.getElementById("syntheseMenu");
if (synthese instanceof HTMLElement)
synthese.classList.add("active");
return 0;
}
function iFrameTestMethod() {
var iframe = document.getElementById('iFrameTest');
console.log(iframe);
//var content = iframe.contentDocument.body;
if (iframe.readyState == 'complete') {
console.log('hoho');
}
}
function checkScrollSpy() {
var scrollSpys = [].slice.call(document.querySelectorAll(".scrollspy-example"));
var scrollSpysLength = scrollSpys.length;
for (var i = scrollSpysLength; i--;) {
var $spy = $(scrollSpys[i]);
$.fn['scrollspy'].call($spy, $spy.data());
}
}
function resizeIFrameToFitContent(iFrame) {
alert("in resizeIFrameToFitContent");
iFrame.height = iFrame.contentWindow.document.body.scrollHeight;
alert(iFrame.height);
}
function resizeiFrames() {
alert("in resizeiFrames");
var iFrame = document.getElementById("iFrame1");
resizeIFrameToFitContent(iFrame);
// or, to resize all iframes:
var iframes = document.querySelectorAll("iframe");
for (var i = 0; i < iframes.length; i++) {
resizeIFrameToFitContent(iframes[i]);
}
return 0;
}
function autoResize(iframe) {
alert(iframe);
var h0 = iframe.contentWindow;
alert(h0);
var h = iframe.contentWindow.document.body.scrollHeight + "px";
alert("h:" + h);
iframe.style.height = h;
}
window.SetFocusToElement = (element) => {
element.focus();
return 0;
};
function getHeight(element) {
return element.offsetHeight;
}
caches.delete("blazor-resources-/").then(function (e) {
console.log("'blazor-resources-/' cache deleted");
});
function RefreshIFramesDashboard() {
var elts = document.getElementsByClassName("refresh");
for (var elt of elts) {
//elt.contentWindow.location.reload();
//elt.parentNode.replaceChild(elt.cloneNode(), elt);
}
}
function RefreshIFramesDashboard(newCohort) {
var elts = document.getElementsByClassName("refreshParent");
for (var elt of elts) {
//elt.contentWindow.location.reload();
//elt.parentNode.replaceChild(elt.cloneNode(), elt);
elt.innerHTML = elt.innerHTML.replace(/Cohort=./, "Cohort=" + newCohort);
}
}
</script>
</head>
<body data-spy="scroll" data-target="#list-example" data-offset="85" class="scrollspy-example" style="position:relative;overflow-y: scroll;scroll-behavior: smooth;">
<app>Loading...</app>
<script src="_content/MudBlazor/MudBlazor.min.js"></script>
<div id="blazor-error-ui">
An unhandled error has occurred.
Reload
<a class="dismiss">🗙</a>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</body>
</html>
thank you.
Try to add MIME Types to iis to slove this issue:
Open IIS Manager and click on your server level settings.
In Features View, double-click MIME Types.
In the Actions pane, click Add.
In the Extension box, type .dll. In the MIME Type box, type application/octet-stream.
Click OK.

display message using JSF

I'm completely new in JSF. I'm using this tutorial: https://www.tutorialspoint.com/jsf
According to it I created a first project. Here's the Java code:
package com.tutorialspoint.test;
import javax.faces.bean.ManagedBean;
#ManagedBean(name = "helloWorld", eager = true)
public class HelloWorld {
public HelloWorld() {
System.out.println("HelloWorld started!");
}
public String getMessage() {
return "Hello World!";
}
}
this is home.xhtml file:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns = "http://www.w3.org/1999/xhtml">
<head>
<title>JSF Tutorial!</title>
</head>
<body>
#{helloWorld.getMessage()}
</body>
</html>
when I enter this address in my browser: http://localhost:8080/helloworld/home.jsf the tab's title "JSF Tutorial!" is displayed but the content (the text "Hello World" not. Could I ask you for some hints what can be missing?
If you need some more information/code from other files, just let me know.
BTW, I'm using Wildfly 10.1.0 as an application server where I deploy the updated .war file.
Thanks in advance.

creating simple reusable component in Apache Tapestry5

I am starting an adventure with Apache Tapestry5. I am trying to make simple component (for tests), consisting of pair of Textfields. Component is named "TestComp". I have following elements:
testComp.tml
<t:container
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd">
<p>
<input t:type="TextField" t:id="testOne" t:value="testOne.input"/><br/>
<input t:type="TextField" t:id="testTwo" t:value="testTwo.input"/><br/>
</p>
</t:container>
TestComp.java
public class TestComp {
private DataContainer testOne;
private DataContainer testTwo;
#SetupRender
public void setup(){
testOne = new DataContainer();
testTwo = new DataContainer();
}
public String getContentOfTestOne() {
return testOne.getInput();
}
public String getContentOfTestTwo() {
return testTwo.getInput();
}
public DataContainer getTestOne() {
return testOne;
}
public void setTestOne(DataContainer testOne) {
this.testOne = testOne;
}
public DataContainer getTestTwo() {
return testTwo;
}
public void setTestTwo(DataContainer testTwo) {
this.testTwo = testTwo;
}
}
And then I am trying to use it in other place, for example in index.tml:
<form t:type="form" t:id="out">
<t:testComp />
<br/><input type="submit" value="Component"/>
</form>
According to dozens of materials and examples I've found (to be honest non of it refereed to case similar to mine) such implementation should result of showing testComp element in the form, but unfotrunately there is nothing rendered above the button (though tapestry is not crashing). What am I missing? And will I be able to put in Index.java property of TestComp type and bind it with my
<t:testComp />
in Index.tml by id (or it requires something more to implement in my custom component?)
Did you provide the full index.tml file? If so, you are missing the tapestry namespace as well as a correctly setup html document. Try the following:
Index.tml
<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd">
<head>
<title>My page</title>
</head>
<body>
<form t:type="form" t:id="out">
<div t:id="testComp" />
<br/><input type="submit" value="Component"/>
</form>
</body>
</html>
In your Index.java you can use this to access your component.
#component(id="testComp")
private TestComp testComp;
If this does not work there is probably something wrong in your configuration or setup and you might just be looking at a static tml file not handled by tapestry at all. In this case follow the step-by-step guide on the Getting Started page.

Allow page layout to hide control on master page

If I want to use my regular master page for a new page layout, except I don't want the main navigation menu control (a 3rd party control) to be visible, how can I let the page layout hide it? In asp.net I would expose a public property or method on the master page and then call it from the child page, but not sure what can be done in SharePoint since there is no code behind or discernible master page class.
I got it working like this but I'm not in love with the implementation.
On Master Page:
...
<c:Menu id="myMenu" runat="server" />
...
</form>
</body>
</html>
<script runat="server">
public bool IsConsumerNavVisible
{
set
{
myMenu.Visible = value;
}
}
</script>
On PageLayout:
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
System.Reflection.PropertyInfo pi = Page.Master.GetType().GetProperty("IsConsumerNavVisible");
pi.SetValue(Page.Master, false, null);
}
</script>
So I exposed a public property on the master page to set the visibility and then used reflection on the PageLayout to find & set that property. I tried putting the PageLayout code in just a <% %> script block and it executed but the menu would end up visible anyway. Putting it in a Page_Load event handler fixed that. If there is a better way I'm all ears.

Sharepoint 2010 JQuery Ajax not working

I have a custom webpart within Sharepoint and am trying to apply some ajax to the webpart.
The same code works within a .net web application but not within a sharepoint web part.
The code from the .net web application is shown below (the aspx page and the code behind) which works fine.:
ASPX File
<%# Page Title="Home Page" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true"
CodeBehind="Default.aspx.cs" Inherits="WebApplication3._Default" %>
<asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="HeadContent">
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
// Add the page method call as an onclick handler for the div.
$("#Result").click(function () {
var loc = window.location.href;
$.ajax({
type: "POST",
url: loc + "/GetMessage",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg) {
// Replace the div's content with the page method's return.
$("#Result").text(msg.d);
}
});
});
});
</script>
</asp:Content>
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
<div id="Result">Click here for the time.</div>
<asp:Button ID="btnClick" runat="server" Text="Button" />
</asp:Content>
.CS File
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.Services;
namespace WebApplication3
{
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
[WebMethod]
public static string GetMessage()
{
return "Codebehind method call...";
}
[WebMethod]
public static string GetDate()
{
return DateTime.Now.ToString();
}
}
}
The text "Click here for the time" changes to "Code behind method call" when I click on it without doing a postback. I can step into the code and this calls the method GetMessage() in the code behind within a .net web application.
However this does not work on a webpart within sharepoint 2010. Does anyone have any ideas?
Another option is to create a SharePoint Application Page. Here is your code slightly modified to work as an Application Page (uses SharePoint Master Page content sections, and the AJAX points to the application page:
<%# Assembly Name="$SharePoint.Project.AssemblyFullName$" %>
<%# Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%# Assembly Name="Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="ApplicationPageWS.aspx.cs" Inherits="WebMethod.Layouts.WebMethod.ApplicationPageWS" DynamicMasterPageFile="~masterurl/default.master" %>
<asp:Content ID="PageHead" ContentPlaceHolderID="PlaceHolderAdditionalPageHead" runat="server">
<SharePoint:ScriptLink ID="ScriptLink1" runat="server" Localizable="false" Name="js/jquery-1.8.2.js"></SharePoint:ScriptLink>
<asp:Content ID="Main" ContentPlaceHolderID="PlaceHolderMain" runat="server">
<script type="text/javascript">
$(document).ready(function () {
// Add the page method call as an onclick handler for the div.
$("#Result").click(function () {
$.ajax({
type: "POST",
url: "**/_layouts/WebMethod/ApplicationPageWS.aspx/GetMessage**",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
$("#Result").text(msg.d);
},
error: function (msg) {
alert(msg.responseText);
}
});
});
});
</script>
<div id="Result">Click here for the time.</div>
<asp:Button ID="btnClick" runat="server" Text="Button" />
</asp:Content>
<asp:Content ID="PageTitle" ContentPlaceHolderID="PlaceHolderPageTitle" runat="server">
Application Page
</asp:Content>
<asp:Content ID="PageTitleInTitleArea" ContentPlaceHolderID="PlaceHolderPageTitleInTitleArea" runat="server" >
My Application Page
</asp:Content>
Next change your service-side to inherit from LayoutsPageBase instead of WebPart:
using System;
using System.Web.UI;
using System.Web.Services;
using Microsoft.SharePoint.WebControls;
namespace WebMethod.Layouts.WebMethod
{
public partial class ApplicationPageWS : LayoutsPageBase
{
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
//InitializeControl();
}
protected void Page_Load(object sender, EventArgs e)
{
}
[WebMethod]
public static string GetMessage()
{
return "Codebehind method call...";
}
[WebMethod]
public static string GetDate()
{
return DateTime.Now.ToString();
}
}
}
Hope this solution work in your situation, if not, and you need to call a web service from a web part, you will need to create the web service outside of your Web Part. This is nicely explained at http://dbremes.wordpress.com/2011/01/03/ajax-style-web-parts-in-sharepoint-the-easy-way/
Steve
First make sure that all needed js files are deployed and loaded correctly. Lookup the urls in the html source and copy them in a new tab and see if they load correctly.
Also try to put all JavaScript files on the server ( so no 'https://ajax.googleapis.com/...' urls). I once had problems with crossdomain scripting permissions.
There might also be a conflict with different JavaScript libraries being loaded. For jQuery within a SharePoint context I usually use the 'noConflict' option.
var $j = jQuery.noConflict();
$j(document).ready(function() {
.....
I just want to say you have to use POST you cannot use a GET found that out the hard way.

Resources