I'm learning how to use React with .NET and am using the Visual Studio templates provided to play around (I'm using a Mac, if that is useful for context). I am starting with very simple back end applications and trying to get my React front end to link to these. I am very new to using React and .NET so I apologise if the questions I ask seem simple. Here is my current issue:
I have the following C# Controller class which retrieves and returns the middle letters of a string:
MiddleLetterController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
namespace TestingReactDotNet.Controllers
{
public class MiddleLetterController : Controller
{
public string GetMiddle(string word)
{
if (word.Length % 2 == 0)
{
return word.Substring(word.Length / 2 - 1, 2);
}
else
{
return word.Substring(word.Length / 2, 1);
}
}
}
}
I am using React on the front end and want whatever the user types and submits in the form to be the word passed as an argument to the GetMiddle() method and for this to be displayed on screen.
My current MiddleLetter.js file is:
import React, { Component } from "react";
export class MiddleLetter extends Component {
state = {
word: "",
};
updateInput(key, value) {
// update react state
this.setState({
[key]: value
});
}
render() {
return (
<center>
<div className="App">
<div>
Type a word...
<br />
<input
type="text"
placeholder="Type word here ..."
value={this.state.word}
onChange={e => this.updateInput("word", e.target.value)}
/>
<button onClick={() => ?????)}>Submit</button>
<br />
</div>
</div>
</center>
);
}
}
I have looked at the React documentation but cannot work out how / the best way to link the React form submission to the backend application. I would be really grateful if anyone had any suggestions please :) Thank you.
You're probably going to want to pull in a library like axios or fetch into your react project "yarn add axios" in your react folder.
Then at the top of your MiddleLetter.js you'll need to import axios from axios;
create an instance of axios in MiddleLetter.js, something like:
const instance = axios.create({
baseURL: "localhost:{whatever port you're running on}",
)}
Then in your "updateInput" function where your comments are add:
const response = await instance.get("/middleletter/" + value);
your response should have the return value from the controller.
Then for your controller.
add [HttpGet({word})]
over public string GetMiddle(string word)
This will let the controller get the word from your URL.
There are better ways to do all of this. But this should get you where you need to go.
Related
I just started to learn Selenium WebDriver and I collided with a few issues.
I googled a lot, but it was unsuccessful.
So, I am going to write a parser of a website.
There is a kind of HTML.
browser view and html
<div class="view-wrapper"> is included
<ul class="sport--list"> and its included a list of <li class="sport--block">...</li>
I am trying to check each class of sport-block's in a loop and found the section which includes key word like "Футбол"
Футбол
Then, when I found the proper section I am going to get value of non-static timer and then write it to file. It's my next step. I have to solve first of all my first trouble;
timer
The main issue is that there are a lot of divs of .
How can I found the proper one? I wrote this code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.UI;
namespace Parser
{
class Program
{
static void Main(string[] args)
{
using (var driver = new ChromeDriver())
{
// Go to the home page
driver.Navigate().GoToUrl("https://www.favorit.com.ua/ru/live/");
// Get the page elements
IList<IWebElement> ClassNamesElements = driver.FindElements(By.ClassName("sport--block"));
for (int i = 0; i < ClassNamesElements.Count; i++)
{
Console.WriteLine(ClassNamesElements[i]);
Console.ReadLine();
}
}
}
}
}
But I don't know how to set up the next condition for selection. Like "Where includes something like Футбол".
And after that, I want to work only within the piece of HTML which corresponds to my proper sport--block
I am not able to use XPath of elements, cuz website is not static. And proper sport block can appear with random positon.
I don't need you write code instead of me. I just need some direction to continue my googling.
DId I choose the proper way to solve this task (C# + Selenium)?
Please, give me a few clues or hints. Thank you in advance.
To retrieve the value of the non-static timer with respect to several keys within the <li class="sport--block">...</li> tags, as there are multiple such <li> tags, you can write a function which will accept the key value as a string argument and print the relevant time.
Function :
public void print_key_timer(string myKey)
{
string myTime = driver.FindElement(By.XPath("//ul[#class='sport--list']//li[#class='sport--block']/div[contains(#class,'sport--head')]//span[.='" + myKey + "']//following-sibling::ul[1]//ul[#class='events--list']//div[#class='event--head']//div[#class='time--block']/div[#class='event--timer']")).GetAttribute("innerHTML");
Console.WriteLine(myTime);
}
Now you can call the function as many times you wish from anywhere within your program as :
print_key_timer("Футбол")
Try this code :
for (int i = 0; i < ClassNamesElements.Count; i++){
if(ClassNamesElements[i].GetText().Contains("Футбол")){
Console.WriteLine(ClassNamesElements[i].GetText());
Console.ReadLine();
}
}
I am trying to scrape http://gameinfo.na.leagueoflegends.com/en/game-info/champions/ but i can't find where the images are of those champions in my webscraping. The problem is that it doesnt scrape every single thing... My script is ...
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Net;
namespace WebScraping
{
class Program
{
static void Main(string[] args) {
WebScraping wb = new WebScraping();
wb.Scraping();
}
class WebScraping
{
public void Scraping()
{
Console.WriteLine("Type in the webpage you want to scrape : \n");
string WebPage = Console.ReadLine();
WebClient webc = new WebClient();
string url = webc.DownloadString(WebPage);`
Console.WriteLine(url += "\n \t Done");
Console.ReadLine();
}
}
}
The thing I'm trying to find is the <a href="amumu"/></a>
You're right: the data is not in the original HTML. Instead, the Champions Grid is populated via javascript. This actually works in your favor; it means you'll probably be able to a get your hero information in json format, which is much easier to parse. The only trick is finding where that javascript is loaded.
In order to do that, load the page in your browser and use the developer tools. I'll use Google Chrome as an example. Hit F12 to open the developer tools, and then go to the Network tab. Now hit Shift+F5 to reload the page the record the requests. With this done, you can look through every individual item that was downloaded to render this page. I saw a full 238 requests (that's a lot!), but if you scan through the list for json items you'll eventually see a champions.json file. Right click on that, and you can get this url:
http://ddragon.leagueoflegends.com/cdn/6.24.1/data/en_US/champion.json
Look at the data in that file, and you'll find this:
"Amumu":
{
"version":"6.24.1",
"id":"Amumu",
"key":"32",
"name":"Amumu",
"title":"the Sad Mummy",
"blurb":"''Solitude can be lonelier than death.''<br><br>A lonely and melancholy soul from ancient Shurima, Amumu roams the world in search of a friend. Cursed by an ancient spell, he is doomed to remain alone forever, as his touch is death and his affection ...",
"info":
{
"attack":2,
"defense":6,
"magic":8,
"difficulty":3
},
"image":
{
"full":"Amumu.png",
"sprite":"champion0.png",
"group":"champion",
"x":192,
"y":0,
"w":48,
"h":48
},
"tags":["Tank","Mage"],
"partype":"MP",
"stats":
{
"hp":613.12,
"hpperlevel":84.0,
"mp":287.2,
"mpperlevel":40.0,
"movespeed":335.0,
"armor":23.544,
"armorperlevel":3.8,
"spellblock":32.1,
"spellblockperlevel":1.25,
"attackrange":125.0,
"hpregen":8.875,
"hpregenperlevel":0.85,
"mpregen":7.38,
"mpregenperlevel":0.525,
"crit":0.0,
"critperlevel":0.0,
"attackdamage":53.384,
"attackdamageperlevel":3.8,
"attackspeedoffset":-0.02,
"attackspeedperlevel":2.18
}
}
Use NuGet to pull in a JSON parser and you can quickly get structured data from this.
Regex helped me match the information that i needed
MatchCollection m1 = Regex.Matches(html, "\"id\":\"(.+?)\",\"", RegexOptions.Singleline);
I am trying to load a html file that is in the same path as class i'm working with Via a web view in xamarin forms when I run the app I get a white screen and nothing loads here's my code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace App.Plan
{
public partial class Tornado : ContentPage
{
public Tornado()
{
InitializeComponent();
var browser = new WebView
{
Source = "local.html"
};
}
}
}
I realize this is old, but the documentation is maybe not entirely clear when it comes to local files so I thought I'd share my thoughts. Hopefully it's helpful to anyone who stumbles here.
The documentation states:
To display local content using a WebView, you'll need to open the HTML file like any other, then load the contents as a string into the Html property of an HtmlWebViewSource.
The key thing to note is that the WebView's Source property is ONLY for external URLs or HtmlWebViewSource. You cannot put a local URL in the Source property. The phrasing "you'll need to open the HTML file like any other" means (as it states shortly after) that you need to load the contents of the file from disk into a variable using a full file path, not URL.
The question then becomes "What about links to other local files?" That's where the BaseUrl property of HtmlWebViewSource comes into play. The documentation addresses this by stating the following:
Although the first page has been loaded, the WebView has no knowledge of where the HTML came from. That is a problem when dealing with pages that reference local resources. Examples of when that might happen include when local pages link to each other, a page makes use of a separate JavaScript file, or a page links to a CSS stylesheet.
In other words, any links to local resources in your HTML will be prepended with the BaseUrl by the Webview automatically.
To sum things up
Create the IBaseUrl Interface in your shared project
public interface IBaseUrl {
string Get();
}
Create the platform-specific implementations of IBaseUrl in each platform project
iOS:
[assembly: Dependency (typeof (BaseUrl_iOS))]
namespace WorkingWithWebview.iOS
{
public class BaseUrl_iOS : IBaseUrl
{
public string Get()
{
return NSBundle.MainBundle.BundlePath;
}
}
}
Android
[assembly: Dependency (typeof(BaseUrl_Android))]
namespace WorkingWithWebview.Android
{
public class BaseUrl_Android : IBaseUrl
{
public string Get()
{
return "file:///android_asset/";
}
}
}
UWP
[assembly: Dependency(typeof(BaseUrl))]
namespace WorkingWithWebview.UWP
{
public class BaseUrl : IBaseUrl
{
public string Get()
{
return "ms-appx-web:///";
}
}
}
Make sure your HTML files are in the appropriate folders and have the proper Build Action
iOS: Resources, build action: "BundleResource"
Android: Assets, build action: "AndroidAsset"
UWP: project root, build action: "content"
Make sure the WebView has a height and width request or it may not render:
It may be necessary to set the WidthRequest and HeightRequest properties of the WebView to see the HTML content, depending upon the layout the WebView is a child of. For example, this is required in a StackLayout.
Once that setup is done, you can put it into action in your shared project. Here's a simplified example:
// Use DI function to get the BaseUrl for the platform
var baseUrl = DependencyService.Get<IBaseUrl>().Get();
// You could append subfolders here if you don't
// want all the HTML files mixed with other resources:
// var baseUrl = System.IO.Path.Combine(DependencyService.Get<IBaseUrl>().Get(), "subfolder");
// Define the location of your initial HTML page using the base url
var initialHtmlPath = System.IO.Path.Combine(baseUrl, "index.html");
// Create the viewsource, loading the first HTML file as a string
var localHtmlViewSource = new HtmlWebViewSource();
localHtmlViewSource.BaseUrl = baseUrl;
localHtmlViewSource.Html = System.IO.File.ReadAllText(initialHtmlPath);
// Set the webview to use the local source
HelpWebView.Source = localHtmlViewSource;
Xamarin has docs in relation to this:
https://developer.xamarin.com/guides/xamarin-forms/user-interface/webview/
var browser = new WebView();
var htmlSource = new HtmlWebViewSource();
htmlSource.Html = #"<html><body>
<h1>Xamarin.Forms</h1>
<p>Welcome to WebView.</p>
</body></html>";
browser.Source = htmlSource;
Here is official sample in github
WorkingWithWebview
tabs.Children.Add (new LocalHtml {Title = "Local" });
tabs.Children.Add (new LocalHtmlBaseUrl {Title = "BaseUrl" });
tabs.Children.Add (new WebPage { Title = "Web Page"});
tabs.Children.Add (new WebAppPage {Title ="External"});
Second tab may help.
I've been trying to evaluate XSockets but it appears I've hit my first stumbling block pretty early. I can connect to Generic controller just fine but custom controllers do not seem to work at all - I get a custom message: "The handler name was not found in loaded plugins". A Google search shows one other person having this problem in SE, but their solution did not work for me.
I've created a console project and installed the latest XSockets 3.03 from NuGet. My code is below:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using XSockets.Core.Common.Socket;
using XSockets.Core.XSocket;
using XSockets.Core.XSocket.Helpers;
using XSockets.Core.Common.Socket.Event.Interface;
namespace XSockets2
{
class Program
{
static void Main(string[] args)
{
using (var server = XSockets.Plugin.Framework.Composable.GetExport<IXSocketServerContainer>())
{
Console.WriteLine("running!");
server.StartServers();
Console.ReadLine();
server.StopServers();
}
}
}
public class TestCont: XSocketController
{
public override void OnMessage(ITextArgs textArgs)
{
this.SendToAll(textArgs);
}
}
}
And my Javascript
function connect2() {
var host = "ws://localhost:4502/testcont";
var conn;
conn = new XSockets.WebSocket(host);
conn.on(XSockets.Events.open, function (clientInfo) {
message(clientInfo.ClientGuid); //appends message to textarea
console.log('Open', clientInfo);
});
conn.on('OnMessage', function (d) {
message(d);
console.log('Message', d);
});
conn.on(XSockets.Events.onError, function (err) {
message(err.CustomMessage);
console.log('Error', err);
});
conn.on(XSockets.Events.close, function () {
message('Closed');
console.log('Closed');
});
First of all the latest version is 3.0.2 (not 3.0.3) but that is not important :)
There is a well known and documented bug in the plugin framework for the latest version. The bug only affect you if you run a console application (or any other *.exe) project since xsockets by default only looks in *.dll and not *.exe.
The issue and work around is described here
But your code will not work anyway since you have an error (from what I can see).
Your controller is named "TestCont" but you connect to "testcont". The connectionstring is case sensitive.
EDIT: I also think you are missunderstanding the method OnMessage since you have added a subscription to that exact name.
In Windows Forms I can create a class file called 'Authentication.cs' with the following code:
public class Authentication
{
public string Name;
internal bool Authenticate()
{
bool i = false;
if (Name == "Jason")
{
i = true;
}
return i;
}
}
In WebMatrix, I can insert a new Class file, called 'Authentication.cs', and insert the above code.
And in my default.cshtml file, I do this:
<body>
#{
Authentication auth = new Authentication();
if(auth.Authenticated("jasonp"))
{
<p>#auth.Authenticated("jasonp");</p>
}
}
</body>
But it won't work! It works for the WinForms desktop app, but not in WebMatrix. I don't know why it's not working. The error message is:
"The namespace Authenticate does not
exist. Are you sure you have
referenced assemblies etc?"
So, then at the top of my default.cshtml file I tried this:
#using Authentication.cs;
Which led to the exact same error!
There's no documentation that I can find anywhere that tells you how to "include" a class file into your WebMatrix pages.
Any help is appreciated,
Thank you!
You import a namespace, not a file. So; what namespace is Authentication in? For example:
#using My.Utils.Authentication.cs;
Also - you want to drop the ; in the razor call:
<p>#auth.Authenticated("jasonp")</p>
You can also provide the fully qualified name in the code:
#{
var auth = new My.Utils.Authentication();
if(auth.Authenticated("jasonp"))
{
<p>#auth.Authenticated("jasonp")</p>
}
}
(aside: are you intentionally calling the same method twice with the same values?)
Just drop the cs file in you App_Code directory
then do something like this
#{
Authentication auth = new Authentication();
if(auth.Authenticated("jasonp"))
{
<p>#auth.Authenticated("jasonp");</p>
}
}
No need to add a using.
Additionally if you wanted to use a .dll then you would need the using
#using NameSpace.Authenication
#{
Authenticated auth = new Authenicated();
}
#if(#auth.Authenticated("jasonp"))
{
<p>#auth.Authenticated("jasonp")</p>
}
Create a file named linkRef.cs
code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
public class linkRef
{
public linkRef() {
//
// TODO: Add constructor logic here
//
}
}
Put it in a folder App_code then by dot net 2012 publish to bin then upload bin folder