Get JSON values from Webview - ios

How can I find Json response value from WebView
Example: There is a one Login URL and we are opening this in Webview use of this we will get token and I want to add this token in user default.

Store your JSON data in a hidden field as a string in your html file.
<input id="TokenInfo" type="hidden" value="YOUR_JSON_DATA"/>
Add following javaScript Code into your html page.
<script>
$(function() {
var tokenInfo = $("#TokenInfo").val();
try {
window.webkit.messageHandlers.scriptHandler.postMessage(tokenInfo); // For iOS
} catch (e) {
//
}
try {
Android.login(tokenInfo); // For Android
} catch (e) {
//
}
})
</script>
From android end you need to add a JavaScriptInterface interface into to web view
final JavaScriptInterface myJavaScriptInterface = new JavaScriptInterface(getContext());
webview.addJavascriptInterface(myJavaScriptInterface, "Android");
public class JavaScriptInterface {
Context mContext;
JavaScriptInterface(Context c) {
mContext = c;
}
#JavascriptInterface
public void login(String tokenInfo) {
// deserialize your json here.
}
}

Related

Blazor WebAssembly Using stream in pdf.js

How can I use a base64 stream in pdf.js inside a Blazor app?
It's easier to use a local path (src="path?file=filePath"), but not good documented how to handle a pdf stream.
Download, unpack and implement pdf.js in your blazor app in wwwroot/lib.
Add at index.html
<script type="text/javascript" src="lib/pdfjs/build/pdf.js"></script>
<script type="text/javascript">
function loadPdf(base64Data) {
try {
var pdfjsframe = document.getElementById('pdfViewer');
if (!base64Data == "") {
pdfjsframe.contentWindow.PDFViewerApplication.open(base64Data);
}
} catch (error) { console.error("Error at pdfjsframe.contentWindow.PDFViewerApplication.open(base64Data)"); }
}
</script>
Add at your page or component.razor:
<iframe id="pdfViewer" src="/lib/pdfjs/web/viewer.html"></iframe>
and in the cs:
public partial class PdfViewerComponent
{
[Parameter]
public int DocumentNumber { get; set; }
private string _stream = "";
protected override async Task OnParametersSetAsync()
{
_stream = await HttpClientService.GetDocumentStreamById(DocumentNumber);
if (!string.IsNullOrEmpty(_stream))
await OpenDocument(_stream);
_stream = ""; // that will ensure that your loading the right pdf at the right time
}
private async Task OpenDocument(string stream)
{
await JSRuntime.InvokeVoidAsync("loadPdf", stream);
}
}
In this example the _stream comes from a API. Put in the property _stream your stream string wherever you will get it from.

How to call a javascript function from webview xamarin android?

I am trying to call a javascript function from my webview xamarin.android app. How can I do it?
Firstly, implement a custom WebClient (look at CustomWebClient inheritance model) which overrides the OnPageFinished (aka OnNavigationCompleted) default behaviout:
WebView webView = new WebView(this);
webView.Settings.JavaScriptEnabled = true;
webView.Settings.AllowUniversalAccessFromFileURLs = true;
webView.LoadUrl("http://yoururl.com");
SetContentView(webView);
And now you can invoke JS directly like
webView.EvaluateJavascript("JS code",null);
The second argument is a callback . Which is a placeholder for the javascript result .You can also define the JavascriptResult as the following:
public class JavascriptResult : Java.Lang.Object, IValueCallback
{
private TaskCompletionSource<string> source;
public Task<string> JsResult => source.Task;
public JavascriptResult()
{
source = new TaskCompletionSource<string>();
}
public void OnReceiveValue(Java.Lang.Object result)
{
try
{
string res = ((Java.Lang.String)result).ToString();
source.SetResult(res);
}
catch (Exception ex)
{
source.SetException(ex);
}
}
}

Showing error message after checking the back-end

My controller is something like this:
[HttpPost]
[Route("Somewhere")]
public JsonResult SetSomething(string propertyName, string propertyValue)
{
var successSave = this.SaveIt(propertyName,propertyValue);
if(successSave)
return Json(propertyValue);
else
// Show a message in front end that there was problem in saving
}
And then my view is currently something like:
#Model.SomethingFeild
That just loads the value and shows it in a textbox field in there .
So how can I change this to be able to handle the psedo-code scenario I wrote in the controller, so that if something is wrong in DB ( not front-end vlaidation) such as duplicate entry, then it comes back and tells the UI that so UI shows a hard coded message?
Wrap it in try catch block and add an extension method for reading exception (or your exception type that is thrown) like so:
[HttpPost]
[Route("Somewhere")]
public JsonResult SetSomething(string propertyName, string propertyValue)
{
try
{
var successSave = this.SaveIt(propertyName, propertyValue);
if (successSave)
return Json(new { success = true, value = propertyValue });
}
catch (Exception ex)
{
return Extensions.ReturnExceptionToView(ex);
}
}
Example extension method (static method):
internal static JsonResult ReturnExceptionToView(Exception ex)
{
List<object> viewErrors = new List<object>();
viewErrors.Add(new { ErrorMessage = ex.ToString() });
return new JsonResult() { Data = (new { success = false, errors = viewErrors }) };
}
Then check for success property in the response in JS. Example below is using response of ajax call and pushing to Knockout observable array.
if (response.success) {
// do something with successful response
} else {
// we have an error in the response.errors collection
$.each(response.errors, function () {
vm.saveErrors.push(new ErrorMsg(this.ErrorMessage));
});

mvc signalr how to display all connected users

I need to build a chat using signalr and I am new in this.
So far I got only the chat by reading some others codes and tutorials and this is what I got:
on my ChatApp.Hubs I got the following code
public static class UserHandler
{
public static HashSet<string> ConnectedIds = new HashSet<string>();
}
public class ChatHub : Hub
{
public void Send(string name, string message)
{
// Call the addNewMessageToPage method to update clients.
Clients.All.addNewMessageToPage(name, message);
}
public override Task OnConnected()
{
UserHandler.ConnectedIds.Add(Context.ConnectionId);
return base.OnConnected();
}
public override Task OnDisconnected(bool stopCalled)
{
UserHandler.ConnectedIds.Remove(Context.ConnectionId);
return base.OnDisconnected(stopCalled);
}
}
and my view I copy past from a tutorial
#{
ViewBag.Title = "Chat";
}
<h2>Chat</h2>
<div class="container">
<input type="text" id="message" />
<input type="button" id="sendmessage" value="Send" />
<input type="hidden" id="displayname" />
<ul id="discussion">
</ul>
</div>
#section scripts {
<!--Script references. -->
<!--The jQuery library is required and is referenced by default in _Layout.cshtml. -->
<!--Reference the SignalR library. -->
<script src="~/Scripts/jquery.signalR-2.1.0.min.js"></script>
<!--Reference the autogenerated SignalR hub script. -->
<script src="~/signalr/hubs"></script>
<!--SignalR script to update the chat page and send messages.-->
<script>
$(function () {
// Reference the auto-generated proxy for the hub.
var chat = $.connection.chatHub;
// Create a function that the hub can call back to display messages.
chat.client.addNewMessageToPage = function (name, message) {
// Add the message to the page.
$('#discussion').append('<li><strong>' + htmlEncode(name)
+ '</strong>: ' + htmlEncode(message) + '</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.
chat.server.send($('#displayname').val(), $('#message').val());
// Clear text box and reset focus for next comment.
$('#message').val('').focus();
});
});
});
// This optional function html-encodes messages for display in the page.
function htmlEncode(value) {
var encodedValue = $('<div />').text(value).html();
return encodedValue;
}
</script>
}
what I need now is to display all the connected users in the view
Appriciate your help
Thanks in advance
So, you pretty much either want to just store all 'Active' connections in some kind of database/storage or a static hashset/dictionary.
You save the ConnectionIds when the user connects and remove them when they disconnect :
Hub
public class ChatHub : Hub
{
static HashSet<string> CurrentConnections = new HashSet<string>();
public override Task OnConnected()
{
var id = Context.ConnectionId;
CurrentConnections.Add(id);
return base.OnConnected();
}
public override System.Threading.Tasks.Task OnDisconnected()
{
var connection = CurrentConnections.FirstOrDefault(x => x == Context.ConnectionId);
if (connection != null)
{
CurrentConnections.Remove(connection);
}
return base.OnDisconnected();
}
//return list of all active connections
public List<string> GetAllActiveConnections()
{
return CurrentConnections.ToList();
}
}
Client
I added a button and an unordered list.
HTML
<button id="show-all-connections">Show Connections</button>
<ul id="user-list">
</ul>
And added this javascript (using jQuery)
$("#show-all-connections").on("click", function () {
debugger;
chatHub.server.getAllActiveConnections().done(function (connections) {
$.map(connections, function (item) {
$("#user-list").append("<li>Connection ID : " + item + "</li>");
});
});
});
Hope this helps.
Update
In your scenario, I don't see any hooks into using a custom UserId Provider or anything, so you're going to have to ask the User for a User Name and save the Connection ID with that.
HTML
JavaScript
$("#add-connection").click(function () {
var name = $("#user-name").val();
if (name.length > 0) {
chatHub.server.connect(name);
}
else {
alert("Please enter your user name");
}
});
Hub
static List<Users> SignalRUsers = new List<Users>();
public void Connect(string userName)
{
var id = Context.ConnectionId;
if (SignalRUsers .Count(x => x.ConnectionId == id) == 0)
{
SignalRUsers .Add(new Users{ ConnectionId = id, UserName = userName });
}
}
public override System.Threading.Tasks.Task OnDisconnected()
{
var item = SignalRUsers.FirstOrDefault(x => x.ConnectionId == Context.ConnectionId);
if (item != null)
{
SignalRUsers.Remove(item);
}
return base.OnDisconnected();
}
Users.cs
public class Users
{
public string ConnectionId { get; set; }
public string UserName { get; set; }
}
This is psuedo code since I am not able to run this code at the moment. Hope it helps and gives you a clear enough direction.

How to make WebView editable on winrt?

I need to create simple HTML editor. I know desktop application I can get access to DOM and set DesignMode=true. How can I do it for WebView in winrt application?
So seems I've found solution how to set DesignMode for WebView in WinRT applications.
I just needed invoke javascript method that could change document.designMode property to "on"
In my case I implemented extension for WebView where added DependencyProperty.
public static class WebViewEx
{
public static readonly DependencyProperty DesignModeProperty = DependencyProperty.RegisterAttached(
"DesignMode", typeof(bool),
typeof(WebViewEx),
new PropertyMetadata(null, OnDesignModePropertyChanged));
private async static void OnDesignModePropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
if (DesignMode.DesignModeEnabled)
return;
WebView view = dependencyObject as WebView;
if (view == null)
return;
if (e.NewValue == e.OldValue)
return;
await view.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () =>
{
if ((bool)e.NewValue)
{
await view.InvokeScriptAsync("eval", new string[] { "document.designMode = \"on\";" });
}
else
{
await view.InvokeScriptAsync("eval", new string[] { "document.designMode = \"off\";" });
}
});
}
public static void SetDesignMode(DependencyObject element, bool value)
{
element.SetValue(DesignModeProperty, value);
}
public static bool GetDesignMode(DependencyObject element)
{
return (bool)element.GetValue(DesignModeProperty);
}
}
That allows me to turn on\off DesignMode from XAML
<WebView x:Name="webViewBody" Source="about:blank" controls:WebViewEx.DesignMode="true"/>
Mandatory requirement to Invoke javascript methods is webview should be initialized. In my case I set source property to "about:blank"

Resources