I'm building a WPF application and try to get the ajax callback data with the WebView2 control.
WebApplication is a simple Login View, and login method code like this:
$("#btn").click(function () {
$.post("loginHandler.ashx",
{
name: $("#name").val(),
pwd: $("#pwd").val()
},
function (data, status) {
var r=JSON.parse(data)
alert(r.result);
});
});
the XAML code in wpf is:
<wv2:WebView2 Name="webView" Source="http://localhost:44372/login.html" />
Now I use the CoreWebView2_WebResourceResponseReceived to get the request and response information, but I can't get the data in the callback function...
After searching around for decent maybe I should use Javascript? Can JS catch another function's callback result?
Please give me some advise, I'm the first time use to controls...
(If WebView2 can't do this, may the CefSharp do that?)
Any assistance is appreciated, THX!
CoreWebView2.WebResourceResponseReceived is raised whenever the WebView2 gets an http(s) response back from a server and you can check the contents and headers for the response.
But if the content you're trying to obtain exists only in JavaScript you can use CoreWebView2.WebMessageReceived and window.chrome.webview.postMessage to send the content from script to your C#.
In script you'd do something along the lines of:
$("#btn").click(function () {
$.post("loginHandler.ashx",
{
name: $("#name").val(),
pwd: $("#pwd").val()
},
function (data, status) {
var r=JSON.parse(data)
// Send data to the host app
chrome.webview.postMessage(r);
});
});
And in your C# you'd hook up a WebMessageReceived event handler something like:
// During initialization after CoreWebView2 property is set
// and before you navigate the webview2 to the page that will
// post the data.
webView.CoreWebView2.WebMessageReceived += ReceiveLoginData;
// ...
}
void ReceiveLoginData(object sender, CoreWebView2WebMessageReceivedEventArgs args)
{
String loginDataAsJson = args.WebMessageAsJson();
// parse the JSON string into an object
// ...
}
You can see more example usage of WebMessageReceived and PostWebMessage in the WebView2 sample app.
Create a html folder in bin/debug/ path :
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="script.js"></script>
</head>
<body>
<div id="demo">lkkkkkkkkkkkkkkkkkkkkkk</div>
<div id="demo1">uuuuuuuuuuuuuuuuuuuuuu</div>
<div id="demo2">pppppppppppppppppppppp</div>
<button onclick="me()">Click me</button>
<button onclick="sendThisItem('hidear')">Clickkkkkkkkkkkkkkkkkkk me</button>
<script>
function me() {
var me = "ddddddddd";
document.getElementById('demo1').style.color = 'yellow';
window.chrome.webview.postMessage('dellmaddddddddddddddddddd');
}
</script>
</body>
</html>
Now in Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using Microsoft.Web.WebView2.Core;
namespace WindowsFormsAppWebview
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
InitwebView();
}
async void InitwebView()
{
await webView21.EnsureCoreWebView2Async(null);
webView21.CoreWebView2.Navigate(Path.Combine("file:", Application.StartupPath, #"html\", "index.html"));
webView21.WebMessageReceived += webView2_WebMessageReceived;
}
private void webView2_WebMessageReceived(object sender, Microsoft.Web.WebView2.Core.CoreWebView2WebMessageReceivedEventArgs args)
{
label1.Text = args.TryGetWebMessageAsString();
}
private void button1_Click(object sender, EventArgs e)
{
label1.Text = "sssssssss";
//MessageBox.Show("hello world ");
webView21.CoreWebView2.ExecuteScriptAsync("document.getElementById('demo').style.color = 'red'");
}
}
}
You need to Create label1,button1 , webView21 in Form.
This line is importent:
webView21.WebMessageReceived += webView2_WebMessageReceived;
Related
What is the correct way to put javascript in an XElement object in C#?
Currently I have the following:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
var tag = new XElement
(
"script",
new XAttribute("type", #"text/javascript"),
#"
$().ready(onLoad);
function onLoad()
{
if (3 > 1){
alert('Hello world');
}
};
"
);
Console.WriteLine(tag.ToString());
Console.ReadKey();
}
}
}
Which gives as output:
<script type="text/javascript">
$().ready(onLoad);
function onLoad()
{
if (3 > 1){
alert('Hello world');
}
};
</script>
But instead of > I actually want >... What am I doing wrong? Is there a correct way to put javascript in an XElement? If not what's the right way?
The following worked. I had to add XCData and put // in front of the XCData element and also // at the end of the javascript.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using System.Web;
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
var tag = new XElement
(
"script",
new XAttribute("type", #"text/javascript"),
"//",
new XCData(#"
$().ready(onLoad);
function onLoad()
{
if (3 > 1){
alert('Hello world');
}
};//")
);
Console.WriteLine(tag.ToString());
Console.ReadKey();
}
}
}
Which gives the following output:
<script type="text/javascript">//<![CDATA[
$().ready(onLoad);
function onLoad()
{
if (3 > 1){
alert('Hello world');
}
};//]]></script>
Now i am developing selfhost signalr server application using VS2012 and client application using HTML/JS WebUI in Mosync IDE. When communication between client and server application, the signalr hub is successfully created on all browser and android emulator. But its doesn't work when i am using USB Debugging on my mobile. its produce 'undefined' message. How to make successful connection on my mobile. Please guide me.
Server side code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Reflection;
using System.IO;
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
using Microsoft.Owin.Hosting;
using Microsoft.Owin.Cors;
using Microsoft.Owin;
using Owin;
namespace SignalRServer
{
public partial class Form1 : Form
{
private IDisposable signalR { get; set; }
public string ServerURI;
MyNewHub h = new MyNewHub();
public Form1()
{
InitializeComponent();
}
private void btnStart_Click(object sender, EventArgs e)
{
writeToConsole("Starting server...");
btnStart.Enabled = false;
Task.Run(() => StartServer());
}
private void StartServer()
{
try
{
//signalR = WebApp.Start(ServerURI);
if (File.Exists(Application.StartupPath + "\\IPAddress.txt"))
{
ServerURI = System.IO.File.ReadAllText(Application.StartupPath + "\\IPAddress.txt").Trim();
signalR = WebApp.Start(ServerURI);
}
else
{
MessageBox.Show("IPAddress not found");
}
}
catch (TargetInvocationException)
{
writeToConsole("Server failed to start. A server is already running on" + ServerURI);
this.Invoke((Action)(() => btnStart.Enabled = true));
return;
}
this.Invoke((Action)(() => btnStart.Enabled = true));
writeToConsole("Server started at" + ServerURI);
}
public void writeToConsole(string message)
{
if (RichTextBoxConsole.InvokeRequired)
{
this.Invoke((Action)(() => writeToConsole(message)));
return;
}
RichTextBoxConsole.AppendText(message + Environment.NewLine);
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (signalR != null)
{
signalR.Dispose();
}
}
private void btnSend_Click(object sender, EventArgs e)
{
string msg = txtMesage.Text;
h.Receive(msg);
}
}
class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseCors(CorsOptions.AllowAll);
app.MapSignalR();
}
}
[HubName("myNewHub")]
public class MyNewHub : Hub
{
public void Send(string name, string message)
{
Clients.All.addMessage(name, message);
Program.mainform.writeToConsole(name + " : " + message);
}
public void Receive(string msg)
{
var context = GlobalHost.ConnectionManager.GetHubContext<MyNewHub>();
context.Clients.All.addMessage("Admin", msg);
}
public override Task OnConnected()
{
Program.mainform.writeToConsole("Client Connected:" + Context.ConnectionId);
return base.OnConnected();
}
public override Task OnDisconnected(bool stopCalled)
{
Program.mainform.writeToConsole("Client DisConnected: " + Context.ConnectionId);
return base.OnDisconnected(stopCalled);
}
}
}
Client side code:
<!DOCTYPE html>
<!--
* #file index.html
*
* Template application that shows examples of how to access
* device services from JavaScript using the Wormhole library.
-->
<html>
<head>
<title>SignalR Simple Chat</title>
<style type="text/css">
.container {
background-color: #99CCFF;
border: thick solid #808080;
padding: 20px;
margin: 20px;
}
</style>
<meta name="viewport" content="width=320, user-scalable=no">
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Wormhole Template App</title>
<link rel="stylesheet" href="style.css" type="text/css" media="screen" title="no title" charset="utf-8">
<script type="text/javascript" charset="utf-8" src="js/wormhole.js"></script>
<script src="js/jquery-1.6.4.min.js"></script>
<script src="js/jquery.signalR-2.0.3.min.js"></script>
<script src="http://192.168.0.7:8080/signalr/hubs"></script>
<script type="text/javascript">
function clientconnect()
{
alert("Start Button Clicked");
$.connection.hub.url = "http://192.168.0.7:8080/signalr";
// Declare a proxy to reference the hub.
var chats = $.connection.myNewHub;
alert(chats);
// Create a function that the hub can call to broadcast messages.
chats.client.addMessage = function (name, message) {
// Html encode display name and message.
var encodedName = $('<div />').text(name).html();
var encodedMsg = $('<div />').text(message).html();
// Add the message to the page.
$('#discussion').append('<li><strong>' + encodedName
+ '</strong>: ' + encodedMsg + '</li>');
};
// Get the user name and store it to prepend to messages.
$('#displayname').val(prompt('Enter your name:', ''));
// Set initial focus to message input box.
$('#message').focus();
// Start the connection.
$.connection.hub.start().done(function () {
$('#sendmessage').click(function () {
// Call the Send method on the hub.
chats.server.send($('#displayname').val(), $('#message').val());
// Clear text box and reset focus for next comment.
$('#message').val('').focus();
});
});
}
</script>
</head>
<body>
<div class="container">
<input type="text" id="message" />
<input type="button" id="sendmessage" value="Send" />
<input type="hidden" id="displayname" />
<input type="button" value="Start" onclick="clientconnect()"/>
<ul id="discussion"></ul>
</div>
</body>
After posting on how to get server side information to JS (on client side) link here, I was advised to create my server side logic into a Web Api in order to expose data via HTTP through a JQuery AJAX call. After looking through a lot of documentation, and even a tutorial series online hosted by Microsoft, I found little to no good instruction. Previously, I was calling my serverside methods through inline C# calls in my js script, but learned that because C# is precompiled, it simply just "fills in" the values returned by the C# functions.
Just for a reference as to how I am improperly calling my C# methods.
This is my front end: Login.aspx
<%# Page Language="C#" AutoEventWireup="true" CodeFile="Login.aspx.cs" Inherits="Login" %>
<!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 runat="server">
<title>PAM testing</title>
<link rel="stylesheet" type="text/css" href="Styles/Site.css" />
<script type="text/javascript" src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
<script type="text/javascript" src="Scripts/JScript.js"></script>
</head>
<body>
<div id="banner">PAM Testing Tool</div>
<div id="content">
<form id="form1" runat="server" style="margin-left: 25%; text-align: center; height: 41px; width: 292px;">
<%--Login ASP Object--%>
<asp:Login ID="Login1" runat="server" onclick="process()"></asp:Login>
<asp:ValidationSummary ID="ValidationSummary1" runat="server" style="text-align: center" ValidationGroup="Login1" />
</form>
<%--TEST AREA--%>
<script type="text/javascript">
function logCookie(){
document.cookie = "user=" + document.getElementById("Login1_UserName").value;// this is the id of username input field once displayed in the browser
}
function testFunction() {
<%=Login1_Authenticate() %>;
}
function process(){
logCookie();
testFunction();
}
</script>
</div>
</body>
</html>
My C# code looks like this
Login.aspx.cs
using System;
using System.Data;
using System.Data.SqlClient;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.EnterpriseServices;
public partial class Login : System.Web.UI.Page
{
int status;
int role;
SqlConnection conn;
SqlCommand command;
SqlDataReader reader;
protected string Login1_Authenticate()
{
// create an open connection
conn =
new SqlConnection("Data Source=xxx;"
+ "Initial Catalog=xxx;"
+ "User ID=xxx;Password=xxx");
conn.Open();
//string userName;
//userName = Convert.ToString(Console.ReadLine());
// create a SqlCommand object for this connection
command = conn.CreateCommand();
command.CommandText = "EXEC dbo.SP_CA_CHECK_USER #USER_ID = '"+Login1.UserName+"', #PASSWORD = '"+Login1.Password+"'";
command.CommandType = CommandType.Text;
// execute the command that returns a SqlDataReader
reader = command.ExecuteReader();
// display the results
while (reader.Read())
{
status = reader.GetInt32(0);
}
// close first reader
reader.Close();
//----------
existTest();
return "the login process is finished";
}
public static string GetData(int userid)
{
/*You can do database operations here if required*/
return "my userid is" + userid.ToString();
}
public string existTest()
{
if (status == 0)
{
//login
Session["userID"] = Login1.UserName;
command.CommandText = "EXEC dbo.SP_CA_RETURN_USER_ROLE #USER_ID = '" + Login1.UserName + "'";
reader = command.ExecuteReader();
while (reader.Read())
{
role = reader.GetInt32(0);
}
Session["roleID"] = role;
if (Session["userID"] != null)
{
string userID = (string)(Session["userID"]);
//string roleID = (string)(Session["roleID"]);
}
Response.Redirect("Home.aspx");
}
else
{
//wrong username/password
}
// close the connection
reader.Close();
conn.Close();
return "process complete";
}
}
How can I convert my C# into Web api's? I would very much appreciate it if any answers could link me to good documentation or tutorials.
Moving this into Web API would require creating a new Web API project, setting up your appropriate controllers, and moving Form Control to parameters to pass into the Controller methods. Please visit this tutorial for more information on getting started with ASP.NET Web MVC: Getting Started With ASP-NET Web API
Please Note: Executing dynamic SQL the way you are doing in the above code leaves your application open to SQL Injection attacks! Please consider using parameterized SQL instead.
Let's say I've the following sample code (JavaScript):
// Client A
var conn = new XSockets.WebSocket([wsUri]);
conn.on(XSockets.Events.open, function (clientInfo) {
conn.publish("some:channel", { text: "hello world" });
});
// Client B (subscriber)
var conn = new XSockets.WebSocket([wsUri]);
conn.on(XSockets.Events.open, function (clientInfo) {
conn.on("some:channel", function(message) {
// Subscription receives no message!
});
});
Client B never receives a message. Note that this is a sample code. You might think that I don't receive the message because Client B got connected after Client A sent the message, but in the actual code I'm publishing messages after both sockets are opened.
The server-side XSocketsController is working because I'm using it for server-sent notifications.
What am I doing wrong? Thank you in advance!
It looks like you have mixed up the pub/sub with the rpc, but I cant tell for sure if you do not post the server side code as well.
But what version are you using? 3.0.6 or 4.0?
Once I know the version and have the server side code I will edit this answer and add a working sample.
EDIT (added sample for 3.0.6):
Just wrote a very simple chat with pub/sub.
Controller
using XSockets.Core.Common.Socket.Event.Interface;
using XSockets.Core.XSocket;
using XSockets.Core.XSocket.Helpers;
namespace Demo
{
public class SampleController : XSocketController
{
/// <summary>
/// By overriding the onmessage method we get pub/sub
/// </summary>
/// <param name="textArgs"></param>
public override void OnMessage(ITextArgs textArgs)
{
//Will publish to all client that subscribes to the value of textArgs.#event
this.SendToAll(textArgs);
}
}
}
HTML/JavaScript
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script src="Scripts/jquery-2.1.1.js"></script>
<script src="Scripts/XSockets.latest.min.js"></script>
<script>
var conn;
$(function() {
conn = new XSockets.WebSocket('ws://127.0.0.1:4502/Sample');
conn.onopen = function(ci) {
console.log('open', ci);
conn.on('say', function(d) {
$('div').prepend($('<p>').text(d.text));
});
}
$('input').on('keydown', function(e) {
if (e.keyCode == 13) {
conn.publish('say', { text: $(this).val() });
$(this).val('');
}
});
});
</script>
</head>
<body>
<input type="text" placeholder="type and hit enter to send..."/>
<div></div>
</body>
</html>
Regards
Uffe
I tried to understand dotnetopenid and failed. I dont know asp.net well enough and i want to do this problematically.
Is there a simple JS openid lib? or a simple/good openid example doing it for a C# desktop application?
Here is an example of open ID in c# .net . Not desktop but web.
http://www.nikhedonia.com/notebook/entry/openid-and-asp-net-mvc/
Here is my aspx file, i only added one line, the WebApplication1.openidtest.Authenticate line
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication1._Default" %>
<!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 runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<% WebApplication1.openidtest.Authenticate("http://your_id.myopenid.com/"); %>
</div>
</form>
</body>
</html>
Here is the cs file. Note it works but doesnt handle things like errors and really is just for testing/breakpoints.
NOTE: If email is required and the user submit a persona that doesnt have an email there will be no email listed thus you must check and handle accordingly.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using DotNetOpenAuth;
using DotNetOpenAuth.OpenId;
using DotNetOpenAuth.OpenId.RelyingParty;
using DotNetOpenAuth.OpenId.Extensions.AttributeExchange;
using DotNetOpenAuth.OpenId.Extensions.SimpleRegistration;
namespace WebApplication1
{
static public class openidtest
{
static public void Authenticate(string openIdIdentifier)
{
var openId = new OpenIdRelyingParty();
var response = openId.GetResponse();
if (UserNeedsToLogin(response))
{
var request = openId.CreateRequest(openIdIdentifier);
request.AddExtension(new ClaimsRequest { Email = DemandLevel.Require });
request.RedirectingResponse.Send();
return;
}
HandleAuthenticationResponse(response);
}
static bool UserNeedsToLogin(IAuthenticationResponse response)
{
return response == null;
}
static void HandleAuthenticationResponse(IAuthenticationResponse response)
{
switch (response.Status)
{
case AuthenticationStatus.Authenticated:
{
var claims = response.GetExtension<ClaimsResponse>();
if (claims != null)
{
var s = claims.Email;
}
return;
//return HandleSuccessfulLogin(response);
}
case AuthenticationStatus.Canceled:
//_context.ErrorMessage = "Login was cancelled at the provider.";
break;
case AuthenticationStatus.Failed:
//_context.ErrorMessage = "Login failed at the provider.";
break;
case AuthenticationStatus.SetupRequired:
//_context.ErrorMessage = "The provider requires setup.";
break;
default:
//_context.ErrorMessage = "Login failed.";
break;
}
}
}
}