Consuming WordPress RSS Feed In ASP.NET - c#

How do I consume my WordPress blog's RSS feed to display my latest blog posts on my homepage? I ran into the following piece of code to do this:
Function GetRSSFeed(strURL as String) as DataTable
'Get the XML data
Dim reader as XmlTextReader = New XmlTextReader(strURL)
'return a new DataSet
Dim ds as DataSet = New DataSet()
ds.ReadXml(reader)
Return ds.Tables(2)
End Function
But it errors out at this line: 'ds.ReadXml(reader)' with the following error:
A column named 'comments' already belongs to this DataTable.
Perhaps it doesn't work since this code is from 2003? Does anyone have a working code sample? Many thanks in advance!

You can use LINQ to XML to read a WordPress RSS feed.
First get the feed. Make a Uri instance out of it.
var rssFeed = new Uri("https://github.com/geersch/feed/");
Then perform a GET request.
var request = (HttpWebRequest) WebRequest.Create(rssFeed);
request.Method = "GET";
var response = (HttpWebResponse) request.GetResponse();
Get the response stream and read it to download the contents of the feed.
using (var reader = new StreamReader(response.GetResponseStream()))
{
var feedContents = reader.ReadToEnd();
//...
}
Still within the above using statement use LINQ to XML to parse the downloaded content and extract the information you need.
var document = XDocument.Parse(feedContents);
var posts = (from p in document.Descendants("item")
select new
{
Title = p.Element("title").Value,
Link = p.Element("link").Value,
Comments = p.Element("comments").Value,
PubDate = DateTime.Parse(p.Element("pubDate").Value)
}).ToList();
Now you can iterate over the results.
foreach(var post in posts)
{
Console.WriteLine(post.Title);
Console.WriteLine(post.Link);
Console.WriteLine(post.Comments);
Console.WriteLine(post.PubDate);
}
Here I just used an anonymous type to capture the output in, but feel free to create your own BlogPost class or something similar which you can use in the LINQ query.
I'm used to C#, so that's why I've used it in my reply. But you can easily convert it. There are some online converters which you can use.
Regarding your issue with the DataSet (which I personally would not use to implement this), it is caused by an item (blog post) having nodes with the same name.
For example:
<comments>...</comments>
<slash:comments>5</slash:comments>
Sure the second one has a different namespace (slash), but DataSet's ReadXml(...) method does not care about namespaces. It tries to create a second column named "comments". That is why you get the exception.
You can still use a DataSet / DataTable if you want to. Just extract the data from the feed using LINQ to XML as shown above.
Then create a DataSet and add a new table to it.
var dataSet = new DataSet();
var blog = new DataTable("Blog");
blog.Columns.Add("Title", typeof(string));
blog.Columns.Add("Link", typeof(string));
blog.Columns.Add("Comments", typeof(string));
dataSet.Tables.Add(blog);
Iterate over the extracted data and add it to the DataTable:
foreach (var post in posts)
{
var newRow = blog.NewRow();
newRow["Title"] = post.Title;
newRow["Link"] = post.Link;
newRow["Comments"] = post.Comments;
blog.Rows.Add(newRow);
}
Voila, we've now fixed your issue by no longer relying on the DataSet's ReadXml(...) method. Download the feed, extract the data you are interested in and persist it.

I would start in the System.ServiceModel.Syndication namespace, there are classes to directly manipulate RSS feeds. In particular, this looks promising:
XmlReader reader = XmlReader.Create("http://your.uri.here/feed.xml");
SyndicationFeed feed = SyndicationFeed.Load(reader);
Then explore the SyndicationFeed class, in particular the Items collection should contain the RSS entries.

I'd start off with the built in classes for RSS/Atom: SyndicationFeed
using (XmlReader reader = XmlReader.Create(url))
{
return SyndicationFeed.Load(reader);
}

This is simply #Christophe Geers's great solution converted to VB, as a function:
Protected Function getWordPressFeed(ByVal strUrl As String) As DataTable
Dim rssFeed = New Uri(strUrl)
Dim request = DirectCast(WebRequest.Create(rssFeed), HttpWebRequest)
request.Method = "GET"
Dim response = DirectCast(request.GetResponse(), HttpWebResponse)
Dim feedContents As String
Using reader = New StreamReader(response.GetResponseStream())
feedContents = reader.ReadToEnd()
End Using
Dim document = XDocument.Parse(feedContents)
Static Dim dcNamespace As XNamespace
dcNamespace = "http://purl.org/dc/elements/1.1/"
Dim posts = (From p In document.Descendants("item") Select New With { _
Key .Title = p.Element("title").Value, _
Key .Link = p.Element("link").Value, _
Key .Author = p.Element(dcNamespace + "creator").Value, _
Key .Description = p.Element("description").Value, _
Key .PubDate = DateTime.Parse(p.Element("pubDate").Value) _
}).ToList()
Dim dataSet = New DataSet()
Dim blog = New DataTable("Blog")
blog.Columns.Add("Title", GetType(String))
blog.Columns.Add("Link", GetType(String))
blog.Columns.Add("Description", GetType(String))
blog.Columns.Add("Author", GetType(String))
blog.Columns.Add("PubDate", GetType(DateTime))
dataSet.Tables.Add(blog)
For Each post In posts
Dim newRow = blog.NewRow()
newRow("Title") = post.Title
newRow("Link") = post.Link
newRow("Description") = post.Description
newRow("Author") = post.Author
newRow("PubDate") = post.PubDate
blog.Rows.Add(newRow)
Next
Return blog
End Function

This is what I use for my wordpress feed reader.
private async void ReadFeed() {
var rssFeed = new Uri("http://truestrengthmd.com/category/blog/feed");
var request = (HttpWebRequest)WebRequest.Create(rssFeed);
request.Method = "GET";
var _response = await request.GetResponseAsync();
var response = (HttpWebResponse)_response;
using (var reader = new StreamReader(response.GetResponseStream()))
{
var feedContents = reader.ReadToEnd();
var document = XDocument.Parse(feedContents);
var posts = (from p in document.Descendants("item")
select new
{
Title = p.Element("title").Value
}).ToList();
foreach (var post in posts)
{
Debug.WriteLine(post.Title);
}
}
}

You can use my Library for this: wprssapi.marcogriep.de
Just a few lines of code. Very easy to do:
//Get an Instance of Wordpress Controller (Singleton)
WordPressFeedController wp = WordPressFeedController.Instance;
//Load all the RSS Articles
wp.LoadRSS("http://www.its-all-about.de/rss");
//Get the Newest Article (Check Docs for other functions)
var rssItem = wp.GetNewestItem();
this.label1.Text = rssItem.Title;
//Text Only, Remove all the HTML Tags - Limit too 300 Chars
this.richTextBox1.Text = wp.RemoveHTMLFromText(rssItem.Summary.Substring(0, 300)) + "...";
//Open RSS Article on Button Click
this.button1.Click += (s, e) => {
Process.Start(rssItem.Id);
};

Related

How to put Content object (in Controller) inside another object to be returned

I have the following code that returns a List in CVS format using Content, which is working fine.
public ContentResult LearningActionMonitoringPageDataAsync(int actionId)
{
//other code
using (var stream = new MemoryStream())
using (var reader = new StreamReader(stream))
using (var writer = new StreamWriter(stream))
using (var csv = new CsvWriter(writer))
{
csv.WriteRecords(resultsToReturn);
writer.Flush();
stream.Position = 0;
text = reader.ReadToEnd();
}
return Content(text, "text/csv");
}
But, what I want to do is, instead of returning the Content, putting it inside another object which contains some other information to be returned, something like this:
List <PageData> pageData = new List <PageData> {
CSVcontent = Content(text, "text/csv"),
PageTitle = "Abc",
//some other data to display on the page
}
However, I could not manage to do it. Any help?
This can be achieved by returning an ActionResult with the Json method, e.g:
List <PageData> pageData = new List <PageData> {
CSVcontent = Content(text, "text/csv"),
PageTitle = "Abc",
//some other data to display on the page
}
return Json(pageData, JsonRequestBehaviour.AllowGet);
Note that if your CSV data is now not the "main" return from the HTTP method, there's no need to have the Content() call, you can just assign it directly, e.g.:
`CSVContent = text`
But it will be up the client to work with that data. Using Json() will automatically set the content type appropriate for JSON.

c# remove object from list if ID value doesn't exist on web link

I have a function that takes all Json values from a Api link and deserializes all of them into an object list. I need to compare the ID value from that object list with all ID values listed here. However using the function i used on the other Api link doesnt work as that returned Json structure, this one doesnt.
// parameters given are "http://www.gw2spidy.com/api/v0.9/json/item-search/iron/" + "1"
var spidyApi_idByName = api_Handler.objFromApi_idToName(spidyApiUrl, startPage);
The function where above code calls to
public static RootObject objFromApi_idToName(string spidyApiUrl, int page)
{
RootObject rootObject = null;
RootObject tempRootObject = null;
do{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(spidyApiUrl + "/" + page);
WebResponse response = request.GetResponse();
using (Stream responseStream = response.GetResponseStream()){
StreamReader reader = new StreamReader(responseStream, Encoding.UTF8);
var jsonReader = new JsonTextReader(reader);
var serializer = new JsonSerializer();
tempRootObject = serializer.Deserialize<RootObject>(jsonReader);
if (rootObject == null){
rootObject = tempRootObject;
}
else{
rootObject.results.AddRange(tempRootObject.results);
rootObject.count += tempRootObject.count;
}
}
page++;
}
while (tempRootObject != null && tempRootObject.last_page != tempRootObject.page);
return rootObject;
}
How can I check if the ID values in spidyApi_idByName exist here and if they don't be removed from the object list.
EDIT, more general info:
I have a textbox where you can enter your search. This is then send to a Api link to conver the text into ID's of the items that match the search.Example searching for iron will return all these values. However I need to check if these items are sellable which there are 2 ways of doing.
I can access this link, these are all ID's of itmes that are sellable and check if which item ID in the object list doesnt exist in above link.
Or take the Item ID that is in the object list and retrieve more information from a different Api link. This link includes a property called Flags, if this propertie has the value "NoSell" it should be removed from the object list. Example link, this item has the property Flags with value NoSell
Short: translate text into item ID, check if this ID is sellable.
Here is how you obtain a list of ids from your https://api.guildwars2.com/v2/commerce/listings link:
List<string> ids = new List<string>();
HttpWebRequest request =
(HttpWebRequest)WebRequest.Create("https://api.guildwars2.com/v2/commerce/listings");
try
{
WebResponse response = request.GetResponse();
using (Stream responseStream = response.GetResponseStream())
{
using (var reader = new StreamReader(responseStream))
{
ids = reader.ReadToEnd().TrimStart('[').TrimEnd(']').Split(',').Select(str => str.Trim())
.ToList();
}
}
}
catch (Exception)
{
throw;
}
return ids;
This is not a JSON, it's a comma separated string. So you need to parse it in order to obtain the list of id's.

Getting Body content from MSMQ

I try to get the content of an item in a MSMQ - Queue.
When I look at that Entry using QueueExplorer the body content is like
[{"$type":"MyProject.MyClass.MyMethod, Messages","CustomerDecision":0,"OrderReferenceoId":"4fdb6be2-bfde-42b0-93fd-47058a326a24"}]
When I try to read the content using the following code, the body just contains weird crap, mostly \0\0 etc.:
message.Formatter = new XmlMessageFormatter();
var reader = new StreamReader(message.BodyStream);
var msgBody = reader.ReadToEnd();
(message is of type System.Messaging.Message)
It was a Coding Issue. The result LOOKED like random rubbish, but just was a unicode characterset. The following solved the problem:
message.Formatter = new BinaryMessageFormatter();
var reader = new StreamReader(message.BodyStream, Encoding.Unicode);
var msgBody = reader.ReadToEnd();

Read content of Web Browser in WPF

Hello Developers I want to read external content from Website such as element between tag . I am using Web Browser Control and here is my code however this Code just fills my Web browser control with the Web Page
public MainWindow()
{
InitializeComponent();
wbMain.Navigate(new Uri("http://www.annonymous.com", UriKind.RelativeOrAbsolute));
}
You can use the Html Agility Pack library to parse any HTML formatted data.
HtmlDocument doc = new HtmlDocument();
doc.Load(wbMain.DocumentText);
var nodes = doc.SelectNodes("//a[#href"]);
NOTE: The method SelectNode accepts XPath, not CSS or jQuery selectors.
var node = doc.SelectNodes("id('my_element_id')");
As I understood from your question, you are only trying to parse the HTML data, and you don't need to show the actual web page.
If that is the case than you can take a very simple approach and use HttpWebRequest:
var _plainText = string.Empty;
var _request = (HttpWebRequest)WebRequest.Create("http://www.google.com");
_request.Timeout = 5000;
_request.Method = "GET";
_request.ContentType = "text/plain";
using (var _webResponse = (HttpWebResponse)_request.GetResponse())
{
var _webResponseStatus = _webResponse.StatusCode;
var _stream = _webResponse.GetResponseStream();
using (var _streamReader = new StreamReader(_stream))
{
_plainText = _streamReader.ReadToEnd();
}
}
Try this:
dynamic doc = wbMain.Document;
var htmlText = doc.documentElement.InnerHtml;
edit: Taken from here.

how to display a string from a rest webservice in windows forms?

how can display a string from a rest webservice in windows forms my xml looks like this:
<string>whatever</string>
How can you display that in a textbox in win forms?
If I try
string uri = string.Format("etc/{0}/{1} Sad.Text, Happy.Text");
XDocument xDoc = XDocument.Load(uri);
string mystring = xDoc.Element("String").Value;
textBox1.Text = mystring;
You get an object reference error?
XML elements are case-sensitive. Try,
string mystring = xDoc.Element("string").Value;
A better way to solve the problem is to not use XML to return a simple string. The media type text/plain is designed to do that. If you are using Microsoft's ASP.NET Web API just return
return new HttpResponseMessage() {
Content = new StringContent("etc/{0}/{1} Sad.Text, Happy.Text")
};
and on the client (using this http://nuget.org/Packages/system.net.http) do,
var httpClient = new HttpClient();
textBox1.Text = httpClient.GetAsync(uri).Result.Content.ReadAsString();
I would use XmlSerializer to get the information out of XML returned by the web service. I am assuming that your XML is just in a string. You could do something like this for your simple example, but this would also work for more complex objects returned by a REST web service.
XmlSerializer xs = new XmlSerializer ( typeof ( string ) );
MemoryStream memoryStream = new MemoryStream(StringToUTF8ByteArray(restResult));
XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);
string textBoxVal = xs.Deserialize(memoryStream);

Categories