UWP WebView calls dynamic JavaScript - javascript

I have studied Window Universal App these days. When working with WebView, I see it can invoke a script inside the html file, but how about executing an external JavaScript script?
WebView webview = new WebView();
webview.Navigate(new Uri("https://www.google.com"));
string script = #"
function getBodyHTML()
{
var innerHTML = document.getElementsByTagName('body')[0].innerHTML;
return innerHTML;
}
";
I want to get the bodyHTML, possibly using something like this:
// pseudo code
webview.IncludeScript(script);
string bodyHTML = webview.ExecuteScript("getBodyHTML()");

oops, just realize that the similar question was answered.
I could do my thing by:
string[] arguments = new string[] {#"document.getElementsByTagName('body')[0].innerHTML;"};
try
{
string bodyHTML = await webview.InvokeScriptAsync("eval", arguments);
}
catch (Exception ex)
{
}

Related

How can I open a PDF file in new tab without saving this file using ASP.NET MVC 5? [duplicate]

I would like to view a PDF file directly in my browser. I know this question is already asked but I haven't found a solution that works for me.
Here is my action's controller code so far:
public ActionResult GetPdf(string fileName)
{
string filePath = "~/Content/files/" + fileName;
return File(filePath, "application/pdf", fileName);
}
Here is my view:
#{
doc = "Mode_d'emploi.pdf";
}
<p>#Html.ActionLink(UserResource.DocumentationLink, "GetPdf", "General", new { fileName = doc }, null)</p>
When I mouse hover the link here is the link:
The problem with my code is that the pdf file is not viewed in the browser but I get a message asking me if I wand to open or save the file.
I know it is possible and my browser support it because I already test it with another website allowing me to view pdf directly in my browser.
For example, here is the link when I mouse hover a link (on another website):
As you can see there is a difference in the generated link. I don't know if this is useful.
Any idea how can I view my pdf directly in the browser?
The reason you're getting a message asking you to open or save the file is that you're specifying a filename. If you don't specify the filename the PDF file will be opened in your browser.
So, all you need to do is to change your action to this:
public ActionResult GetPdf(string fileName)
{
string filePath = "~/Content/files/" + fileName;
return File(filePath, "application/pdf");
}
Or, if you need to specify a filename you'll have to do it this way:
public ActionResult GetPdf(string fileName)
{
string filePath = "~/Content/files/" + fileName;
Response.AddHeader("Content-Disposition", "inline; filename=" + fileName);
return File(filePath, "application/pdf");
}
Instead of returning a File, try returning a FileStreamResult
public ActionResult GetPdf(string fileName)
{
var fileStream = new FileStream("~/Content/files/" + fileName,
FileMode.Open,
FileAccess.Read
);
var fsResult = new FileStreamResult(fileStream, "application/pdf");
return fsResult;
}
Change your code to this :
Response.AppendHeader("Content-Disposition","inline;filename=xxxx.pdf");
return File(filePath, "application/pdf");
If you read the file stored in database image column, you can use like this:
public ActionResult DownloadFile(int id)
{
using (var db = new DbContext())
{
var data =
db.Documents.FirstOrDefault(m => m.ID == id);
if (data == null) return HttpNotFound();
Response.AppendHeader("content-disposition", "inline; filename=filename.pdf");
return new FileStreamResult(new MemoryStream(data.Fisier.ToArray()), "application/pdf");
}
}
If you are using Rotativa package to generate PDF, Then don't put a name to file with FileName attribute like below example.
return new PartialViewAsPdf("_JcPdfGenerator", pdfModel);
Hope this is helpful to someone.
Although previous posts are often correct; I think most of them are not best practice!
I'd like to suggest to change action return types to FileContentResult and usereturn new FileContentResult(fileContent, "application/pdf"); at the end of action body.
Yes You Can do It Simply by redirecting . it ends extension like u need , .pdf ..
protected void OpenPdfPdf_Click(object sender, EventArgs e)
{
Response.Redirect("jun.pdf");
}
Or another Method ,its opens like .aspx page--
protected void OpenPdf_Click(object sender, EventArgs e)
{
string path = Server.MapPath("jun.pdf");
//or you want to load from url change path to
//string path="https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf";
WebClient client = new WebClient();
Byte[] buffer = client.DownloadData(path);
if (buffer != null)
{
Response.ContentType = "application/pdf";
Response.AddHeader("content-length", buffer.Length.ToString());
Response.BinaryWrite(buffer);
}
}

How to render a WebUserControl client-side

I created a web user control which has some ASP.NET and third-party controls.
I've already tested my control in the markup of a page and it works well.
<APP:MyControl ID="myControl1" InitializeWithValue="Employee" />
<APP:MyControl ID="myControl2" InitializeWithValue="Supplier" />
Now, I want to render this control in the same page but not when the page renders at the first time. In fact, I will click a button which will call a callback and in that moment I want to render the control.
I was trying to do something like this.
void ICallbackEventHandler.RaiseCallbackEvent(string eventArgument)
{
MyControl c1 = new MyControl();
c1.InitializeWithValue = Person.Enum.Employee; //<--CRASH
System.Text.StringBuilder sb = new System.Text.StringBuilder();
System.IO.StringWriter sw = new System.IO.StringWriter(sb);
HtmlTextWriter hw = new HtmlTextWriter(sw);
c1.RenderControl(hw);
return sb.ToString();
}
Then on my client-side receiver
Test
<div id="divControls"></div>
<script>
function receiver(arguments, context) {
document.getElementById('divControls').innerHTML = arguments;
}
</script>
But it crash at the moment of the initialization because all the inner controls of the WebUserControl are null. They have not been initialized.
This is the property of the control
[Browsable(true)]
public Person.Enum InitializeWithValue
{
get { return this.enumPersonValue; }
set
{
this.enumPersonValue = value;
//Literal control
this.litPersonType.Text = "Employee"; //<-- CRASH because litPersonType is null.
}
}
Some can help me to correct this or suggest me another way render a web control but client-side?
UserControls usually are tighted to the Page Life Cycle, so you would need to recreate a whole page and render it instead.
Second, you should load your usercontrol using its .ascx file and not only its class, this is required because only your class is not enough.
You can still try to do like you was doing only creating but using Page.LoadControl:
void ICallbackEventHandler.RaiseCallbackEvent(string eventArgument)
{
MyControl c1 = (MyControl)page.LoadControl("/Controls/myControl.ascx");
c1.InitializeWithValue = Person.Enum.Employee; //<--CRASH
System.Text.StringBuilder sb = new System.Text.StringBuilder();
System.IO.StringWriter sw = new System.IO.StringWriter(sb);
HtmlTextWriter hw = new HtmlTextWriter(sw);
c1.RenderControl(hw);
return sb.ToString();
}
But if your control has Events related to the Page Life Cycle you might need to create a whole context to it:
You can do it all like this:
using (var stringWriter = new StringWriter())
{
using (var page = new Page())
{
MyControl myControl = (MyControl)page.LoadControl("/Controls/myControl.ascx");
var head = new HtmlHead();
page.Controls.Add(head);
var form = new HtmlForm();
page.Controls.Add(form);
var div = new HtmlGenericControl("div");
div.ID = "myControlContent";
form.Controls.Add(div);
div.Controls.Add(myControl);
HttpContext.Current.Server.Execute(page, stringWriter, false);
}
return stringWriter.ToString()
}
Then in your JS you can parse the whole html and get only the innerHTML of div#myControlContent, for example:
function receiver(arguments, context) {
var parser = new DOMParser();
var doc = parser.parseFromString(arguments, "text/html");
document.getElementById('divControls').innerHTML = doc.getElementById('myControlContent').innerHTML;
}
note that DOMParser, is available only in mordern browsers, but you can find other approachs for older browsers...

EO.WebBrowser set referer C#

Trying to find a way to set the referer in EO.WebBrowser.
I saw that the User-Agent can be changed with:webView1.CustomUserAgent but looks like there is no method for the referer. Are there any other ways to get this working in javascript or by other means?
I can "capture" the beforesendheaders event, with this: webView1.BeforeSendHeaders += new EO.WebBrowser.RequestEventHandler(webView1_BeforeSendHeaders);, but doesn't help that much.
I'm working on a project, and I started with awesomium, but... looks like some websites are not loaded, it's just showing a blank screen. I've managed to change both referer and user agent in awesomium, but I really need both to move on.
Any suggestions are appreciated.
Looks like I've found it myself, using javascript.
Here's the code:
public partial class Form1 : Form
{
private const string JS_referer_function = "function navigateToUrl(url) {var f = document.createElement(\"FORM\"); f.action = url; var indexQM = url.indexOf(\"?\"); if (indexQM>=0) { var params = url.substring(indexQM+1).split(\"&\"); for (var i=0; i<params.length; i++) { var keyValuePair = params[i].split(\"=\"); var input = document.createElement(\"INPUT\"); input.type=\"hidden\"; input.name = keyValuePair[0]; input.value = keyValuePair[1]; f.appendChild(input); } } document.body.appendChild(f); f.submit(); }";
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
webView1.LoadUrlAndWait("http://referer.com");
webView1.EvalScript(JS_referer_function);
webView1.EvalScript("navigateToUrl(\"http://192.168.0.108/referer\");");
}
}
It's basically loading http://referer.com first, and using javascript, goes to http://192.168.0.108/referer using the referer http://referer.com.

Create application based on Website

I searched and tried a lot to develop an application which uses the content of a Website. I just saw the StackExchange app, which looks like I want to develop my application. The difference between web and application is here:
Browser:
App:
As you can see, there are some differences between the Browser and the App.
I hope somebody knows how to create an app like that, because after hours of searching I just found the solution of using a simple WebView (which is just a 1:1 like the browser) or to use Javascript in the app to remove some content (which is actually a bit buggy...).
To repeat: the point is, I want to get the content of a website (on start of the app) and to put it inside my application.
Cheers.
What you want to do is to scrape the websites in question by getting their html code and sorting it using some form of logic - I recomend xPath for this. then you can implement this data into some nice native interface.
You need however to be very aware that the data you get is not allways formated the way you want so all of your algorithems have to be very flexible.
the proccess can be cut into steps like this
retrive data from website (DefaultHttpClient and AsyncTask)
analyse and retrive relevant data (your relevant algorithm)
show data to user (Your interface implementation)
UPDATE
Bellow is some example code to fetch some data of a website it implements html-cleaner libary and you will need to implement this in your project.
class GetStationsClass extends AsyncTask<String, String, String> {
#Override
protected String doInBackground(String... params) {
HttpClient httpclient = new DefaultHttpClient();
httpclient.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
httpclient.getParams().setParameter(CoreProtocolPNames.HTTP_ELEMENT_CHARSET, "iso-8859-1");
HttpPost httppost = new HttpPost("http://ntlive.dk/rt/route?id=786");
httppost.setHeader("Accept-Charset", "iso-8859-1, unicode-1-1;q=0.8");
try {
// Add your data
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(3);
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs, "utf-8"));
// Execute HTTP Post Request
HttpResponse response = httpclient.execute(httppost);
int status = response.getStatusLine().getStatusCode();
String data = "";
if (status != HttpStatus.SC_OK) {
ByteArrayOutputStream ostream = new ByteArrayOutputStream();
response.getEntity().writeTo(ostream);
data = ostream.toString();
} else {
BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(),
"iso-8859-1"));
String line = null;
while ((line = reader.readLine()) != null) {
data += line;
}
XPath xpath = XPathFactory.newInstance().newXPath();
try {
Document document = readDocument(data);
NodeList nodes = (NodeList) xpath.evaluate("//*[#id=\"container\"]/ul/li", document,
XPathConstants.NODESET);
for (int i = 0; i < nodes.getLength(); i++) {
Node thisNode = nodes.item(i);
Log.v("",thisNode.getTextContent().trim);
}
} catch (XPathExpressionException e) {
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
//update user interface here
}
}
private Document readDocument(String content) {
Long timeStart = new Date().getTime();
TagNode tagNode = new HtmlCleaner().clean(content);
Document doc = null;
try {
doc = new DomSerializer(new CleanerProperties()).createDOM(tagNode);
return doc;
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return doc;
}
to run the code above use
new getStationsClass.execute();

Capturing console.log within a UIWebView

I'm writing an iOS application with MonoTouch that does some javascript interaction with a UIWebView. For debugging purposes, it would be nice to be able to "capture" console.log in the javascript that runs in the UIWebView together with the rest of the application output. Is this possible? Examples using regular Objective-C code is also OK.
After some more googling, I came about this answer: Javascript console.log() in an iOS UIWebView
Converting it to MonoTouch yields this solution:
using System;
using System.Web;
using System.Json;
using MonoTouch.UIKit;
namespace View
{
public class JsBridgeWebView : UIWebView
{
public object BridgeDelegate {get;set;}
private const string BRIDGE_JS = #"
function invokeNative(functionName, args) {
var iframe = document.createElement('IFRAME');
iframe.setAttribute('src', 'jsbridge://' + functionName + '#' + JSON.stringify(args));
document.documentElement.appendChild(iframe);
iframe.parentNode.removeChild(iframe);
iframe = null;
}
var console = {
log: function(msg) {
invokeNative('Log', [msg]);
}
};
";
public JsBridgeWebView ()
{
ShouldStartLoad += LoadHandler;
LoadFinished += (sender, e) => {
EvaluateJavascript(BRIDGE_JS);
};
}
public bool LoadHandler (UIWebView webView, MonoTouch.Foundation.NSUrlRequest request, UIWebViewNavigationType navigationType)
{
var url = request.Url;
if(url.Scheme.Equals("jsbridge")) {
var func = url.Host;
if(func.Equals("Log")) {
// console.log
var args = JsonObject.Parse(HttpUtility.UrlDecode(url.Fragment));
var msg = (string)args[0];
Console.WriteLine(msg);
return false;
}
return true;
}
}
}
}
Now all console.log statements in javascript in a UIWebView will be sent to Console.WriteLine. This could of course be extended to any kind of output one would want.
Can you add javascript code that does something like this to overwrite the method:
console.log = function(var text) {
consoleforios += text;
}
Then from the web view, call:
string console = webView.EvaluatingJavaScript("return consoleforios;");
This might not be something I'd leave in permanently, but it should work.

Categories

Resources