C# Linking your searchbox to a different websites' searchbox - c#

Is there a way to search a different website from within your own website?
for example, I build a ASP.net page with a search box that's linked for example to stackoverflow's search box, when I type in any search query I'll get the results in my website.

There are a few ways to go about doing something like this:
I'll assume that the intent is to make it work with stack overflow
1. Use StackOverflows Built in API (Client Side)
You can find some details about it here. Included in there are details about how to do a search. You can do this with a client side library like jQuery.
var URL = "http://api.stackoverflow.com/1.1/";
var _url = URL + 'users?filter=locrizak';
$.ajax({
dataType: 'jsonp',
jsonp: 'jsonp', // <--- add this
url: _url,
success: function(val) {
console.log('success');
},
error: function(val) {
console.log('error');
console.log(arguments);
}
});
2. Use StackOverflows Built in API (Server Side)
static void SearchStackOverflow(string y)
{
var httpWebRequest = (HttpWebRequest)WebRequest.Create("http://api.stackoverflow.com/1.1/search?intitle=" + Uri.EscapeDataString(y));
httpWebRequest.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;
httpWebRequest.Method = "GET";
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
string responseText;
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
responseText = streamReader.ReadToEnd();
}
var result = (SearchResult)new JavaScriptSerializer().Deserialize(responseText, typeof(SearchResult));
.... do something with result ...
}
class SearchResult
{
public List<Question> questions { get; set; }
}
class Question
{
public string title { get; set; }
public int answer_count { get; set; }
}
3. Use a Screen Scraper (Not Ideal When an API is available)
This can be done with a tool like Selenium or Watin. Here is a guide to help you get started with Selenium.

Related

Cannot POST data using UnityWebRequest in Unity, it gives Error: HTTP/1.1 500 Internal Server Error

I cannot POST data in Json Format using UnityWebRequest in Unity. It gives error
Error: HTTP/1.1 500 Internal Server Error
I am using Webservice made in ASP.NET Core and hosted locally on IIS Express.
Here is my C# Code in Unity
public class AddUsers : MonoBehaviour
{
IEnumerator addOrUpdateUser()
{
User user = new User()
{
Id = "0001",
Name = "John",
}
UnityWebRequest req = UnityWebRequest.Post("http://localhost:58755/User/AddNewUser", JsonConvert.SerializeObject(user));
req.SetRequestHeader("Content-Type", "application/json");
req.certificateHandler = new BypassCertificate();
yield return req.SendWebRequest();
if (req.isNetworkError || req.isHttpError || req.isError)
print("Error: " + req.error);
print(req.downloadHandler.text);
}
}
[Serializable]
public class UserDetails
{
public string Id { get; set; }
public string Name { get; set; }
}
Here is my ASP.NET Core Code using Entity Framework Core
[HttpPost]
string AddNewUser([FromBody]User user)
{
Context.LogoQuizUsers.Add(user); // I am getting System.NullReferenceException here
Context.SaveChanges();
return "Inserted Id: " + user.Id;
}
Post data as raw - body just as you would send using Postman or any similar interface.
Set Request's UploadHandler as UploadHandlerRaw. Add and Change your statement
UnityWebRequest req = UnityWebRequest.Post("http://localhost:58755/User/AddNewUser", "POST");
req.uploadHandler = new UploadHandlerRaw(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(user))) as UploadHandler;
Hence the final code will be
IEnumerator addOrUpdateUser()
{
//...
UnityWebRequest req = UnityWebRequest.Post("http://localhost:58755/User/AddNewUser", "POST");
req.SetRequestHeader("Content-Type", "application/json");
req.uploadHandler = new UploadHandlerRaw(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(user))) as UploadHandler;
req.certificateHandler = new BypassCertificate();
yield return req.SendWebRequest();
if (req.isNetworkError || req.isHttpError || req.isError)
print("Error: " + req.error);
print(req.downloadHandler.text);
//...
}
Rest of the code is correct.
Look at this topic
Inside the Unity editor:
Go to Window -> Package Manager.
In the topbar of the new window, search the "Packages : XXXXXX" drop-down and select "Unity Registry".
Search the "WebGl publisher" and install / import it.
IIIFFF the package doesn't appear:
In the same Package manager windows, click the "+" button -> Add from git.
Add the following:
com.unity.connect.share
This will automatically add the WebGL Publisher.
It helped me to resolve the problem

Bot Framework v4 Loading Facebook Webview

I'm trying to figure out how to get the MS Bot Framework v4 to work with the Facebook Web View. Currently there isn't anything on the entire internet on how to get this working. There are some examples, like this one, showing how it can work with BF v3.
What I can't figure out is how this works with HeroCards and CardActions in v4.
It seems from the documentation that this type of feature would require an ActionTypes that included a value for web_url which that enum completely ommits. Suggesting this feature isn't supported in BF v4.
I'm currently porting a Botman PHP Bot to MS Bot Framework at it seems it's extremely trivial to do this in Botman by simple calling enableExtensions() on the button element.
I've tried too many approaches to list here but the current attempt looks like this:
var viewButton = new CardAction(
"web_url",
"View Details",
null,
"",
"",
"https://myurl",
JObject.FromObject(new { messenger_extensions = true }));
I've gone through all the domain whitelisting processes so I'm sure that is all ready to go, However, with my current attempts in place Messenger just errors as it seems Favebook dislikes the JSON the Bot Framework is producing.
I've also tried sub-classing the CardAction class like this:
public class WebViewCardAction : CardAction
{
public WebViewCardAction(string displayText, string url)
{
Type = "web_url";
Url = url;
Title = displayText;
MessengerExtensions = true;
WebviewHeightRatio = "compact";
}
[JsonProperty(PropertyName = "url")]
public string Url { get; set; }
[JsonProperty(PropertyName = "webview_height_ratio")]
public string WebviewHeightRatio { get; set; }
[JsonProperty(PropertyName = "messenger_extensions")]
public bool MessengerExtensions { get; set; }
}
Which when looking at the JSON in the Bot Framework emulator produces JSON like this:
{
"messenger_extensions": true,
"title": "View Details",
"type": "web_url",
"url": "https://myurl",
"webview_height_ratio": "compact"
}
Which seems to agree with the stuff I can find in the examples for FB messenger. But with this in place FB messenger errors without even displaying the HeroCard.
Has anyone got this working?
Are there any examples online to look at?
Because the activity schema has not changed, the example you linked also works in V4:
private async Task TestFacebookWebview(ITurnContext turnContext,
CancellationToken cancellationToken)
{
var reply = turnContext.Activity.CreateReply();
var attachment = new
{
type = "template",
payload = new
{
template_type = "button",
text = "Your 🍕 is on it's way!",
buttons = new[]
{
new
{
type = "web_url",
url = "https://mybot.azurewebsites.net/",
title = "See on map",
webview_height_ratio = "compact",
messenger_extensions = true,
},
},
},
};
reply.ChannelData = JObject.FromObject(new { attachment });
await turnContext.SendActivityAsync(reply, cancellationToken);
}
As you can see, there's no need for hero cards or card actions. In this example, the Facebook webview is invoked using a button template that's passed through the ChannelData, which is metadata in the activity that's specific to the channel. Messenger reads that data and creates something that looks like a card for you.
Make sure you whitelist your domain in order for this to work.

Facebook Shared Link - Scrape blog page right after published

I'm developing a blog website (using Umbraco) where it also can share its blog page to Facebook automatically after the page has been published. I have created a Facebook app and used Facebook SDK for .NET in order to that and it works but one small problem is that when the link is shared for the first time, it looks ugly. No image, no title and no description, just url. I have to publish the second time to get the proper link. Heres what I've done so far:-
Programmatically use the scrape API using Facebook SDK for .NET. I even tried to loop through the scrape API 10x to test if it work but doesn't.
Supply the necessary Open Graph Tag in the header of the shared page.
og:title
og:description
og:image
og:image:width
og:image:height
og:type
og:fb_id
og:site_name
I'm using Umbraco ContentService Events to invoke the Facebook API functions:-
public class PublishEventHandler : ApplicationEventHandler
{
protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
ContentService.Published += ContentServicePublished;
}
private void ContentServicePublished(IPublishingStrategy sender, PublishEventArgs<IContent> args)
{
foreach (var node in args.PublishedEntities)
{
foreach (var item in node.Properties)
{
//check property alias and its value
if (item.Alias == "autoPost" && (int)item.Value == 1)
{
var fbClient = new FacebookAuthClient();
var pageToken = fbClient.GetPageToken();
var url = umbraco.library.NiceUrlWithDomain(node.Id);
fbClient.ScrapePage(url, pageToken);
fbClient.SharePostOnPage(url, pageToken);
}
}
}
}
}
Scrape API function:-
public void ScrapePage(string url, string pageToken)
{
var scrapeResult = new FacebookClient(pageToken)
{
Version = "v2.9"
};
var response = scrapeResult.Post(new { id = url, scrape = "true" });
LogHelper.Info(this.GetType(), "|SCRAPE| " + response.ToString());
}
Share API function:-
public void SharePostOnPage(string url, string pageToken)
{
if (pageToken != null)
{
var result = new FacebookClient(pageToken)
{
Version = "v2.9"
};
var response = result.Post("/" + AuthConfig.facebookPageId + "/feed", new { link = url, scrape = "true" });
LogHelper.Info(this.GetType(), "|SHARE| " + response.ToString());
}
}
One more thing I want to add is when I checked the response for the scrape in the log. I only get the id and url but when I used the Graph API Explorer in https://developers.facebook.com I got the whole information of the page (id,url,title,description,etc..) and yes I've been Googling and researching for a week now for this problem before deciding to post this.

Get file with querystring from formData on c# server side using xmlhttprequest

I have been stuck on this for a couple hours now and not even google can help anymore. I am trying to send a file from the client to the backend using xmlhttprequest. I cannot get the filename, type, or content on the C# side. I would appreciate help on doing this. A lot of code I came across had methods that I can only guess are not supported in ASP.Net 5 and MVC 6 (such as HttpContext.Current and HttpPostedFile)
Here is my client side JavaScript request. This sends the query strings which bind to my model no problem so that is easily accessible, but getting the file is what I am having trouble with.
var form = new FormData();
form.append("file", file);
var queryParams = "id=" + (id == null ? -1 : id);
queryParams += "&name=" + name;
queryParams += "&value=" + val;
xhrAttach(REST_DATA + "/attach?" + queryParams, form, function (item) {
console.log('attached: ', item);
alert(item.responseText);
row.setAttribute('data-id', item.id);
removeProgressIndicator(row);
setRowContent(item, row);
}, function (err) {
console.log(err);
//stop showing loading message
stopLoadingMessage();
document.getElementById('errorDiv').innerHTML = err;
});
function xhrAttach(url, data, callback, errback)
{
var xhr = new createXHR();
xhr.open("POST", url, true);
//xhr.setRequestHeader("Content-type", "multipart/form-data");
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
if(xhr.status == 200){
callback(parseJson(xhr.responseText));
}else{
errback("Error: "+xhr.responseText);
}
}
};
xhr.timeout = 1000000;
xhr.ontimeout = errback;
xhr.send(data);
}
Here is my Controller dealing with the request. attachment is a model and the query string binds to it no problem. I could not find out how to add a File parameter to the model, or if that would even matter. Things I have tried are under this code.
// POST: /api/db/attach
[Route("/api/[controller]/attach")]
[HttpPost]
public async Task<dynamic> attach(Attachment attachment)
{
//get the file somehow
}
i have tried many things, but cannot remember exactly what, here is one thing I did try though, which did not work.
var file = Request.Form["file"];
here is the attachment model in case it helps
namespace MyModel.Models
{
public class Attachment
{
public long id { get; set; }
public string name { get; set; }
public string value { get; set; }
}
}
Don't use query parameters or FormData if you're going to use a model on the MVC side. Just don't. And to me, it's better to just get the file into a base64 string first, than to try sending the File object, itself. I've posted about how to do that, here: Convert input=file to byte array
Then, declare and format a JSON object:
var dataObj = {
file = fileByteArray[0],
id = (id == null ? -1 : id),
name = name,
value = val
};
That fileByteArray[0] is referencing the object from my link. My answer there assumes you were just going to keep loading file base64 strings into that global array object. You can either keep it as an array, like I had, and loop through them one by one, replacing that [0] with [i], for example, as the indexer in a for loop, or just use a var fileByteArray = "" with that other code, make it so you don't push additional files but always just overwrite that variable, & just use that.
And a word of caution on that last parameter - don't use val if you use jQuery - it's a keyword. I only have it above because it's what you were passing to the URL parameter values.
Get rid of the queryParams in this line:
xhrAttach(REST_DATA + "/attach?" + queryParams, form, function (item) {
Change it to:
xhrAttach(REST_DATA + "/attach", form, function (item) {
Set the Content-Type, right where it's commented out, to:
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
Change what you are sending - it's no longer going to be FormData, it's the JSON object, and it needs to be stringified:
xhr.send(JSON.stringify(dataObj));
Fix your model to now include the file base64 string:
public class Attachment
{
public string file { get; set; }
public long id { get; set; }
public string name { get; set; }
public string value { get; set; }
}
Fix your POST method. 2 issues:
You can't use [HttpPost] if your class is inheriting ApiController, which you probably should be for this. It must be [System.Web.Http.HttpPost], and yes, it has to be completely spelled out, or it will assume it's [System.Web.Mvc.HttpPost] and not assign the route - you'd get a 404 - Not Found error when you try to do your POST. If you're inheriting from Controller, disregard this.
You will need a [FromBody] tag on your model if you are inheriting from ApiController:
public async Task<dynamic> attach([FromBody]Attachment attachment) { ... }
Then you get the file like this:
string base64FileString = attachment.file;
If you want to store it in a byte[] in the database, you can convert it:
byte[] bytes = System.Convert.FromBase64String(base64FileString);
And btw, I think your response handling is wrong. I would not do this:
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
if(xhr.status == 200){
callback(parseJson(xhr.responseText));
}else{
errback("Error: "+xhr.responseText);
}
}
};
This is how I would do it:
xhr.onreadystatechange = function(response){
if(xhr.readyState == 4 && xhr.status == 200){
callback(parseJson(response.target.responseText));
} else {
alert("Error: " + response.target.responseText);
}
};
Assuming that the response.target.responseText is getting the error sent back from the server-side in a way you can display. If not, sending it to a function that could parse it out would be the right choice. I don't think that xhr.responseText was correct.
I would suggest trying the following:
public async Task<dynamic> attach([FromURI]Attachment attachment, [FromBody] FormDataCollection formData)
And then the FormDataCollection should have the form data for retrieval.
Add a public get/set property called File to your Attachment model and the uploaded file should be bound to this property.
A model similar to yours:
https://github.com/aspnet/Mvc/blob/9f9dcbe6ec2e34d8a0dfae283cb5e40d8b94fdb7/test/WebSites/ModelBindingWebSite/Models/Book.cs#L8
public class Book
{
public string Name { get; set; }
public IFormFile File { get; set; }
}
Following controller has examples of different ways of model binding an uploaded file.
https://github.com/aspnet/Mvc/blob/9f9dcbe6ec2e34d8a0dfae283cb5e40d8b94fdb7/test/WebSites/ModelBindingWebSite/Controllers/FileUploadController.cs#L81
public KeyValuePair<string, FileDetails> UploadModelWithFile(Book book)
{
var file = book.File;
var reader = new StreamReader(file.OpenReadStream());
var fileContent = reader.ReadToEnd();
var parsedContentDisposition = ContentDispositionHeaderValue.Parse(file.ContentDisposition);
var fileDetails = new FileDetails
{
Filename = parsedContentDisposition.FileName,
Content = fileContent
};
return new KeyValuePair<string, FileDetails>(book.Name, fileDetails);
}
if this does not work, then I suspect your request is not in correct format.

Sending an array as part of a PUT method in C#

I am currently developing an app for Windows Phone 8 in C# that makes use of Quizlet.com's API, an online flashcard website.
One of the API calls documented in their API reference to edit a flashcard set requires you to send an array of terms and definitions through a PUT method.
Presumably do this you would have to use HttpWebRequest rather than WebClient, as the latter is too simple and doesn't support PUT requests to my knowledge. I cannot, however, seem to understand how you could send an entire array as part of a PUT request.
Does anyone have any ideas as to how one would do this? I'm sorry I don't have source code to attach, but it's probably not necessary as this is a more general question.
Thanks in advance!
This is the code I'm currently using that is not working:
RestClient Edit = new RestClient("https://api.quizlet.com");
RestRequest EditRequest = new RestRequest();
EditRequest.AddParameter("term_ids[]", ID);
EditRequest.AddParameter("terms[]", Terms);
EditRequest.AddParameter("definitions[]", Definitions);
EditRequest.AddParameter("title", item.Title);
EditRequest.AddHeader("Authorization", "Bearer " + CurrentLogin.AccessToken);
EditRequest.AddHeader("Host", "api.quizlet.com");
EditRequest.Resource = "2.0/sets/" + item.Id;
EditRequest.Method= Method.PUT;
Edit.ExecuteAsync(EditRequest, Response =>
{
FinalizeUpdate(Response);
});
I declare my arrays as such:
int[] ID;
string[] Terms;
string[] Definitions;
And I add data to my arrays as such (TermsList is an ObservableCollection):
foreach(Term i in TermsList)
{
ID[Counter] = i.Id;
Terms[Counter] = i.Name;
Definitions[Counter] = i.Definition;
Counter++;
}
Below is the class definition for Term:
public class Term
{
[JsonProperty("id")]
public int Id { get; set; }
[JsonProperty("term")]
public string Name { get; set; }
[JsonProperty("definition")]
public string Definition { get; set; }
}
The API is RESTful, so I would recommend using an external library if possible, such as RestSharp.
From what I can see in online examples of other APIs, the way to send an array is simply to send the same parameter again with a different value.
i.e., using RestSharp's API you would do :
client.AddParameter("imageData[]", data1);
client.AddParameter("imageData[]", data2);
Just in case anyone else runs into this problem, this is code that finally got the PUT method to work:
RestClient Edit = new RestClient("https://api.quizlet.com");
RestRequest EditRequest = new RestRequest();
foreach (var i in ID)
{
EditRequest.AddParameter("term_ids[]", i);
}
foreach (var i in Terms)
{
EditRequest.AddParameter("terms[]", i);
}
foreach(var i in Definitions)
{
EditRequest.AddParameter("definitions[]", i);
}
EditRequest.AddParameter("title", item.Title);
EditRequest.AddHeader("Authorization", "Bearer " + CurrentLogin.AccessToken);
EditRequest.AddHeader("Host", "api.quizlet.com");
EditRequest.Resource = "2.0/sets/" + item.Id;
EditRequest.Method= Method.PUT;
Edit.ExecuteAsync(EditRequest, Response =>
{
FinalizeUpdate(Response);
});
I hope this helps!

Categories

Resources