I am working on rss feed reader project for Windows Phone. I use the construct below for reading feed in.
It seems to work fine for the 200+ feeds I track - apart for two feeds from NASA
"http://www.nasa.gov/rss/dyn/TWAN_vodcast.rss"
"http://www.nasa.gov/rss/dyn/TWAN_podcast.rss"
for which I get quite frequently problems. Not always and not the same feed, but a few times a week instead of nice utf-8 textual rss feed I get non textual stuff starting (in decimal)
31, 65533, 8, 0, 0..
The strange thing is that reading the feed at the same time with e.g. Chrome shows always good textual result.
Is there something trivial I am missing here? Some black magic that Chrome can do but Windows Phone cannot? Is there some way I can "fix" in my app what Windows Phone fails here? For compatibility reasons I am building for WP7.8 on VS Express 2012
(and yes, I e-mailed to feed owner some time ago but did not get any reply)
public void GetFeed(string _RssUri)
{
WebClient wc = new WebClient();
wc.OpenReadCompleted += wc_OpenReadCompleted;
wc.OpenReadAsync(new Uri(_RssUri));
}
void wc_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
if (e.Error == null)
{
using (StreamReader sr = new StreamReader(e.Result, true))
{
_feedString = sr.ReadToEnd();
}
Assert.IsTrue("0:60 1:63 2:120 3:109 4:108 5:32" == decodeStringContent(rssContent), "Feed does not start with '<?xml '");
// doSomething(_feedString);
}
}
public static string decodeStringContent(string _in, int _maxItems = 5)
{
string _decoding = "";
int _i = 0;
foreach (char x in _in)
{
if (_decoding != "") _decoding = _decoding + " ";
_decoding = _decoding + _i++.ToString() + ":" + Convert.ToInt32(x);
if (_maxItems > 0 && _i > _maxItems) break;
}
return _decoding;
}
Not sure about those particular issues you have had. I also have a feed reader app in the WP8 store and I haven't run into that particular problem when I preview a new feed. I tried with those two feeds and both worked ok.
I pasted a block of code that may help you. A lot of the code you won't need but it should give you a basis to start from.
using FeedModel.Classes;
using FeedModel.Helpers;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Xml.Linq;
namespace FeedModel
{
public class FeedDiscovery
{
private delegate void HttpGetDelegate(IAsyncResult asynchronousResult);
private enum FeedType { RSS, Atom, RDF }
public void FindFeeds(SearchFeedsCallback callback, string searchString)
{
string url = "https://ajax.googleapis.com/ajax/services/feed/find";
string args = string.Format("v=1.0&q={0}", searchString);
httpGet(url, args, (IAsyncResult asynchronousResult) =>
{
try
{
HttpWebRequest sidrequest = (HttpWebRequest)asynchronousResult.AsyncState;
// End the operation
HttpWebResponse response = (HttpWebResponse)sidrequest.EndGetResponse(asynchronousResult);
Stream streamResponse = response.GetResponseStream();
StreamReader streamRead = new StreamReader(streamResponse);
string subscriptionContent = streamRead.ReadToEnd();
// Close the stream object
streamResponse.Close();
streamRead.Close();
// Release the HttpWebResponse
response.Close();
JObject jobj = JObject.Parse(subscriptionContent);
JArray subscriptions = (JArray)((JObject)jobj["responseData"])["entries"];
List<FDFeedItem> feeds =
(from f in subscriptions
select new FDFeedItem()
{
Title = WebBrowserHelper.StripHtml((string)f["title"]),
XmlUrl = (string)f["url"],
Description = WebBrowserHelper.StripHtml((string)f["contentSnippet"]),
HtmlUrl = (string)f["link"],
}).ToList();
callback(new SearchFeedsEventArgs(feeds)
{
Failed = false,
Error = "",
});
// return;
}
catch
{
callback(new SearchFeedsEventArgs(new List<FDFeedItem>())
{
Failed = true,
Error = "Failed",
});
}
});
}
public void FeedPreview(FeedPreviewCallback callback, string url)
{
try
{
httpGet(url, "", (IAsyncResult asynchronousResult) =>
{
try
{
HttpWebRequest sidrequest = (HttpWebRequest)asynchronousResult.AsyncState;
// End the operation
HttpWebResponse response = (HttpWebResponse)sidrequest.EndGetResponse(asynchronousResult);
Stream streamResponse = response.GetResponseStream();
StreamReader streamRead = new StreamReader(streamResponse);
string subscriptionContent = streamRead.ReadToEnd();
XDocument doc = XDocument.Parse(subscriptionContent);
FeedType feedType = FeedType.RSS;
if (doc.Root.ToString().StartsWith("<feed xmlns") || doc.Root.ToString().StartsWith("2005/Atom\">"))
feedType = FeedType.Atom;
List<Article> articles;
string title = "";
string description = "";
switch (feedType)
{
case FeedType.RSS:
articles = ParseRss(doc, out title, out description);
break;
case FeedType.RDF:
articles = ParseRdf(doc, out title, out description);
break;
case FeedType.Atom:
articles = ParseAtom(doc, out title, out description);
break;
default:
throw new NotSupportedException(string.Format("{0} is not supported", feedType.ToString()));
}
FDFeedItem feed = new FDFeedItem();
feed.Title = title;
feed.Description = description;
feed.XmlUrl = url;
callback(new FeedPreviewEventArgs(articles, feed)
{
Failed = false,
Error = ""
});
}
catch
{
callback(new FeedPreviewEventArgs(new List<Article>(), new FDFeedItem())
{
Failed = true,
Error = "Failed to get articles"
});
}
});
}
catch
{
callback(new FeedPreviewEventArgs(new List<Article>(), new FDFeedItem())
{
Failed = true,
Error = "Failed"
});
}
}
public void GetFeedDetails(FeedDetailsCallback callback, string url)
{
try
{
httpGet(url, "", (IAsyncResult asynchronousResult) =>
{
try
{
HttpWebRequest sidrequest = (HttpWebRequest)asynchronousResult.AsyncState;
// End the operation
HttpWebResponse response = (HttpWebResponse)sidrequest.EndGetResponse(asynchronousResult);
Stream streamResponse = response.GetResponseStream();
StreamReader streamRead = new StreamReader(streamResponse);
string subscriptionContent = streamRead.ReadToEnd();
XDocument doc = XDocument.Parse(subscriptionContent);
callback(new FeedsDetailsEventArgs(new FDFeedItem())
{
Failed = false,
Error = ""
});
}
catch
{
callback(new FeedsDetailsEventArgs(new FDFeedItem())
{
Failed = true,
Error = "Failed to get feed"
});
}
});
}
catch
{
callback(new FeedsDetailsEventArgs(new FDFeedItem())
{
Failed = true,
Error = "Failed"
});
}
}
private void httpGet(string requestUrl, string getArgs, HttpGetDelegate httpGetResponse)
{
string url = requestUrl;
if (getArgs != "")
url = string.Format("{0}?{1}", requestUrl, getArgs);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "GET";
request.BeginGetResponse(new AsyncCallback(httpGetResponse), request);
}
/// <summary>
/// Parses an Atom feed and returns a <see cref="IList<Item>"/>.
/// </summary>
private List<Article> ParseAtom(XDocument doc, out string title, out string description)
{
title = doc.Root.Elements().First(i => i.Name.LocalName == "title").Value;
try
{
description = doc.Root.Elements().First(i => i.Name.LocalName == "subtitle").Value;
}
catch { description = ""; }
try
{
var entries = from item in doc.Root.Elements().Where(i => i.Name.LocalName == "entry")
select new Article
{
Content = item.Elements().First(i => i.Name.LocalName == "content").Value,
Url = item.Elements().First(i => i.Name.LocalName == "link").Attribute("href").Value,
PublishedDate = ParseDate(item.Elements().First(i => i.Name.LocalName == "published").Value),
Title = item.Elements().First(i => i.Name.LocalName == "title").Value,
Summary = WebBrowserHelper.GetSummary(item.Elements().First(i => i.Name.LocalName == "content").Value),
CrawlTime = DateTime.ParseExact("01/01/1970", "dd/MM/yyyy", CultureInfo.InvariantCulture),
Author = item.Elements().First(i => i.Name.LocalName == "author").Elements().First(i=> i.Name.LocalName == "name").Value ,
Read = false,
Starred = false,
FeedProviderName = "NewsBlur",
OpenMode = ArticleOpenMode.UseContent,
Image = WebBrowserHelper.ExtractFirstImageFromHTML(item.Elements().First(i => i.Name.LocalName == "content").Value),
};
return entries.ToList();
}
catch
{
return new List<Article>();
}
}
/// <summary>
/// Parses an RSS feed and returns a <see cref="IList<Item>"/>.
/// </summary>
private List<Article> ParseRss(XDocument doc, out string title, out string description)
{
title = "";
description = "";
try
{
//XDocument doc = XDocument.Load(url);
// RSS/Channel/item
var root = doc.Root.Descendants().First(i => i.Name.LocalName == "channel"); //.Elements() .First(i => i.Name.LocalName == "description").Value;
title = root.Elements().First(i => i.Name.LocalName == "title").Value;
description = root.Elements().First(i => i.Name.LocalName == "description").Value;
var entries = from item in root.Elements().Where(i => i.Name.LocalName == "item")
select new Article
{
Content = item.Elements().First(i => i.Name.LocalName == "description").Value,
Url = item.Elements().First(i => i.Name.LocalName == "link").Value,
PublishedDate = ParseDate(item.Elements().First(i => i.Name.LocalName == "pubDate").Value),
Title = item.Elements().First(i => i.Name.LocalName == "title").Value,
Summary = WebBrowserHelper.GetSummary(item.Elements().First(i => i.Name.LocalName == "description").Value),
//Author = WebBrowserHelper.GetSummary(item.Elements().First(i => i.Name.LocalName == "creator").Value),
Author = "",
Read = false,
Starred = false,
FeedProviderName = "NewsBlur",
OpenMode = ArticleOpenMode.UseContent,
Image = WebBrowserHelper.ExtractFirstImageFromHTML(item.Elements().First(i => i.Name.LocalName == "description").Value),
};
return entries.ToList();
}
catch (Exception e)
{
return new List<Article>();
}
}
/// <summary>
/// Parses an RDF feed and returns a <see cref="IList<Item>"/>.
/// </summary>
private List<Article> ParseRdf(XDocument doc, out string title, out string description)
{
title = "";
description = "";
try
{
//XDocument doc = XDocument.Load(url);
// <item> is under the root
var entries = from item in doc.Root.Descendants().Where(i => i.Name.LocalName == "item")
select new Article
{
Content = item.Elements().First(i => i.Name.LocalName == "description").Value,
FeedUrl = item.Elements().First(i => i.Name.LocalName == "link").Value,
PublishedDate = ParseDate(item.Elements().First(i => i.Name.LocalName == "date").Value),
Title = item.Elements().First(i => i.Name.LocalName == "title").Value,
Summary = WebBrowserHelper.GetSummary(item.Elements().First(i => i.Name.LocalName == "description").Value),
Image = WebBrowserHelper.ExtractFirstImageFromHTML(item.Elements().First(i => i.Name.LocalName == "description").Value),
OpenMode = ArticleOpenMode.UseContent,
};
return entries.ToList();
}
catch
{
return new List<Article>();
}
}
private DateTime ParseDate(string date)
{
DateTime result;
if (DateTime.TryParse(date, out result))
return result;
else
{
int i = date.LastIndexOf(" ");
if (i > date.Length - 6)
{
date = date.Substring(0, i).Trim();
if (DateTime.TryParse(date, out result))
return result;
}
return DateTime.MinValue;
}
}
private string GetSummary(string content)
{
string lContent = content.Trim('\"');
int contentLength = 800;
if (lContent.Length < 800)
contentLength = lContent.Length;
string _localContent = "";
try
{
_localContent = WebBrowserHelper.StripHtml(lContent.Substring(0, contentLength));
}
catch
{
}
if (_localContent.Length > 150)
_localContent = _localContent.Substring(0, 150) + "...";
return _localContent;
}
}
}
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Newtonsoft.Json.Linq;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Globalization;
namespace FeedModel.Classes
{
public enum ArticleOpenMode {OpenWebPage,UseContent, Mobilizer};
public class Article
{
private string _id;
protected DateTime _publishedDate;
protected DateTime _crawlTime;
private string _author;
private string _title;
private string _content;
private string _summary;
private string _url;
protected bool _read;
protected bool _starred;
private string _rawDate;
private string _rawCrawlTime;
private ArticleOpenMode _openMode;
protected List<string> _tags;
private string _feedProviderName;
private string _feedTitle;
private string _feedUrl;
private string _feedId;
private string _image;
private AccountTypes _accountType;
public Article()
{
_tags = new List<string>();
_image = "";
}
public ArticleOpenMode OpenMode
{
get { return _openMode; }
set { _openMode = value; }
}
public bool Read
{
get { return _read; }
set { _read = value; }
}
public bool Starred
{
get { return _starred; }
set { _starred = value; }
}
public string Image
{
get { return _image; }
set { _image = value; }
}
public string FeedProviderName
{
get { return _feedProviderName; }
set { _feedProviderName = value; }
}
public string FeedTitle
{
get { return _feedTitle; }
set { _feedTitle = value; }
}
public string FeedUrl
{
get { return _feedUrl; }
set { _feedUrl = value; }
}
public string FeedId
{
get { return _feedId; }
set { _feedId = value; }
}
public string Url
{
get { return _url; }
set { _url = value; }
}
public string Content
{
get { return _content; }
set { _content = value; }
}
public string Summary
{
get { return _summary; }
set { _summary = value; }
}
public string Title
{
get { return _title; }
set { _title = value; }
}
public string Author
{
get { return _author; }
set { _author = value; }
}
public DateTime PublishedDate
{
get { return _publishedDate; }
set { _publishedDate = value; }
}
public DateTime CrawlTime
{
get { return _crawlTime; }
set { _crawlTime = value; }
}
public string Id
{
get { return _id; }
set { _id = value; }
}
public List<string> Tags
{
get { return _tags; }
set { _tags = value; }
}
public string RawPublishDate
{
get { return _rawDate; }
set
{
Double seconds;
_rawDate = value;
try
{
seconds = Convert.ToDouble(_rawDate);
DateTime origin = new DateTime(1970, 1, 1, 0, 0, 0, 0);
_publishedDate = origin.AddSeconds(seconds);
}
catch
{
_publishedDate = DateTime.Now;
}
}
}
public string RawCrawlTime
{
get { return _rawCrawlTime; }
set
{
Double seconds;
_rawCrawlTime = value;
//try
//{
// seconds = Convert.ToDouble(_rawCrawlTime);
// DateTime origin = new DateTime(1970, 1, 1, 0, 0, 0, 0);
// _crawlTime = origin.AddSeconds(seconds);
//}
//catch
//{
_crawlTime = DateTime.Now;
//}
}
}
public AccountTypes AccountType
{
get { return _accountType; }
set { _accountType = value; }
}
}
}
Related
I have asp.net core 3.1 web api project which leverages Azure SQL database as its data storage option. At present I am also using Azure Redis Cache to improve performance of the application.
Here goes the code details :
ICacheProvider.cs:
public interface ICacheProvider
{
IList<string> GetKeys();
IList<string> GetKeys(string strGroup);
T Get<T>(string strKey, string strGroup = "");
bool Set(string strKey, object objData, string strGroup = "", int? intMinutes = null);
bool Remove(string strKey, string strGroup = "");
bool RemoveGroup(string strGroup);
bool ClearCache();
Task<bool> ClearCacheAsync();
}
CacheProvider.cs
public class CacheProvider : ICacheProvider
{
private static readonly int ExpiryMinutes = ConfigManager.Get(CacheExpiryMinutes, CacheExpiryMinutes);
private static Lazy<ConnectionMultiplexer> _objCacheConn = CreateConnection();
private static Lazy<ConnectionMultiplexer> CreateConnection()
{
return new Lazy<ConnectionMultiplexer>(() =>
{
string conn = ConfigManager.Get(RedisConnString);
return ConnectionMultiplexer.Connect(conn);
});
}
private ConnectionMultiplexer Connection
{
get
{
return _objCacheConn.Value;
}
}
private IDatabase GetDatabase()
{
return Connection.GetDatabase();
}
private EndPoint[] GetEndPoints()
{
return Connection.GetEndPoints();
}
private IServer GetServer()
{
var objEndpoint = GetEndPoints().First();
return Connection.GetServer(objEndpoint);
}
public IList<string> GetKeys()
{
return GetKeys("*");
}
public IList<string> GetKeys(string strGroup)
{
var lstKeys = new List<string>();
try
{
var objServer = GetServer();
if (objServer != null)
{
var strPattern = strGroup + ":*";
var objRedisKeys = objServer.Keys(pattern: strPattern);
var objLst = objRedisKeys.GetEnumerator();
while (objLst.MoveNext())
{
lstKeys.Add(objLst.Current.ToString());
}
}
}
catch (Exception)
{
lstKeys = new List<string>();
}
return lstKeys;
}
public T Get<T>(string strKey, string strGroup = "")
{
T objData = default(T);
try
{
var objCache = GetDatabase();
if (!strKey.IsEmpty() && objCache != null)
{
strKey = (strGroup.IsEmpty() ? C.CacheGroups.General : strGroup) + ":" + strKey;
var strData = objCache.StringGet(strKey).ToString();
if (!strData.IsEmpty())
{
objData = JsonConvert.DeserializeObject<T>(strData);
}
}
}
catch (Exception)
{
objData = default(T);
}
return objData;
}
public bool Set(string strKey, object objData, string strGroup = "", int? intMinutes = null)
{
bool blnSuccess = false;
try
{
var objCache = GetDatabase();
if (!strKey.IsEmpty() && objData != null && objCache != null)
{
intMinutes = intMinutes ?? ExpiryMinutes;
strKey = (strGroup.IsEmpty() ? C.CacheGroups.General : strGroup) + ":" + strKey;
var strData = JsonConvert.SerializeObject(objData);
var tsExpiry = new TimeSpan(0, intMinutes.Value, 0);
blnSuccess = objCache.StringSet(strKey, strData, tsExpiry);
}
}
catch (Exception)
{
blnSuccess = false;
}
return blnSuccess;
}
public bool Remove(string strKey, string strGroup = "")
{
bool blnSuccess = false;
try
{
var objCache = GetDatabase();
if (!strKey.IsEmpty() && objCache != null)
{
strKey = (strGroup.IsEmpty() ? C.CacheGroups.General : strGroup) + ":" + strKey;
blnSuccess = objCache.KeyDelete(strKey);
}
}
catch (Exception)
{
blnSuccess = false;
}
return blnSuccess;
}
public bool RemoveGroup(string strGroup)
{
bool blnSuccess = false;
try
{
var lstKeys = GetKeys(strGroup);
var objCache = GetDatabase();
if (lstKeys.Count > 0 && objCache != null)
{
foreach (var strKey in lstKeys)
{
objCache.KeyDelete(strKey);
}
blnSuccess = true;
}
}
catch (Exception)
{
blnSuccess = false;
}
return blnSuccess;
}
public bool ClearCache()
{
bool blnSuccess = false;
try
{
var objServer = GetServer();
if (objServer != null)
{
objServer.FlushAllDatabases();
blnSuccess = true;
}
}
catch (Exception)
{
blnSuccess = false;
}
return blnSuccess;
}
public async Task<bool> ClearCacheAsync()
{
// Get server details
var server = GetServer();
if (server is null)
return false;
// Flush All Databases
await server.FlushAllDatabasesAsync();
return true;
}
}
I am consuming the above CacheProvider in my code as mentioned below :
private async Task<IReadOnlyList<TestInfo>> GetDataAsync(int Id1, int Id2, int Id3, string cacheKey)
{
var data = _cacheProvider.Get<IReadOnlyList<TestInfo>>(cacheKey, TestCacheGroup);
if (data is null)
{
data = await _test.GetSampleDataAsync(Id1, Id2, Id3);
_cacheProvider.Set(cacheKey, data, TestCacheGroup, Defaults.CacheExpiryMinutes);
}
return data;
}
LazyCache by default uses MemoryCache under the hood. I came through documentation that LazyCache can be extended to swap out to redis or casandra at a later time but keep the same code and API.
Can anyone help me here with some code sample which will serve as a reference for my implementation
Below is a modified implementation of MvxLang.
My goal is to be able to implement screen reader text concisely with existing string values stored in <ViewModelName>.json files in our projects Resources, as well as dynamically generated text retrieved from <ViewModelName>.cs files.
I wish to use the following syntax:
xct:SemanticEffect.Description="{mvx:MvxLang ViewModel.SomeStringFromCsFile | SomeStringFromJsonFile | ViewModel.SomeOtherStringFromCsFile}"
This way our ViewModels/Xaml will not be bloated with screen reader text logic/markup.
My implementation works fine when only retrieving string value from <ViewModelName>.json files, but I wish to use a variety of values from <ViewModelName>.cs files as well...
My troubles occur in this block of code when calling GetValue(), I can return the value, but it appears IMarkupExtensions are called before the the ViewModel:
var prefix = "ViewModel.";
if (str.Contains(prefix))
{
var vm = (rootObject is MvxContentPage)
? ((MvxContentPage)rootObject).GetViewModel()
: ((MvxContentView)rootObject).GetViewModel();
PropertyInfo prop = vm.GetType().GetProperty(str.Replace(prefix, string.Empty));
var propValue = prop.GetValue(vm);
return propValue as string ?? string.Empty;
}
Is there a way to return the runtime values here?
Here is the rest of the code:
[ContentProperty("Source")]
public class MvxLang : IMarkupExtension
{
readonly static IMvxTextProvider _textProvider = Mvx.IoCProvider.Resolve<IMvxTextProvider>();
public static string TransitioningViewModel { private get; set; }
public string Source { set; get; }
public object ProvideValue(IServiceProvider serviceProvider)
{
var valueProvider = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
var rootProvider = serviceProvider.GetService(typeof(IRootObjectProvider)) as IRootObjectProvider;
object rootObject = null;
if (rootProvider == null)
{
var propertyInfo = valueProvider.GetType()
.GetTypeInfo()
.DeclaredProperties
.FirstOrDefault(dp => dp.Name.Contains("ParentObjects"));
var parentObjects = (propertyInfo.GetValue(valueProvider) as IEnumerable<object>).ToList();
rootObject = parentObjects.Last();
}
else
rootObject = rootProvider.RootObject;
var name = string.Empty;
if (!(rootObject is MvxContentPage || rootObject is MvxContentView))
{
// Transitioning
name = TransitioningViewModel;
}
else
{
var page = (VisualElement)rootObject;
name = page.GetType().BaseType.GetGenericArguments()[0].Name;
}
if (!string.IsNullOrEmpty(name))
{
var value = string.Empty;
(bool, string) targetPropertyCheck = this.TargetPropertyCheck_ADA(valueProvider.TargetProperty);
if (targetPropertyCheck.Item1)
{
value = ProvideValue_ADA(targetPropertyCheck.Item2, _textProvider, rootObject, name, Source);
return value;
}
else
{
value = _textProvider.GetText(name, Source);
return value;
}
}
return string.Empty;
}
public (bool, string) TargetPropertyCheck_ADA(object targetProperty)
{
var propertyName = string.Empty;
var isADA = false;
if (targetProperty is BindableProperty _targetProperty)
{
if (_targetProperty.DeclaringType.Name.Equals("SemanticEffect"))
{
propertyName = _targetProperty.PropertyName;
isADA = propertyName.Equals("Description") || propertyName.Equals("Hint");
}
}
return (isADA, propertyName);
}
public string ProvideValue_ADA( string propertyName, IMvxTextProvider textProvider, object rootObject, string name, string keyString)
{
if (!string.IsNullOrEmpty(keyString) && !string.IsNullOrEmpty(propertyName))
{
switch (propertyName)
{
case "Description":
if (keyString.Contains('|'))
{
var parameters = keyString.Split(new char[] { '|' });
IEnumerable<string> appliedStrings = parameters.Select(s =>
{
var str = s.Trim();
var prefix = "ViewModel.";
if (str.Contains(prefix))
{
var vm = (rootObject is MvxContentPage)
? ((MvxContentPage)rootObject).GetViewModel()
: ((MvxContentView)rootObject).GetViewModel();
PropertyInfo prop = vm.GetType().GetProperty(str.Replace(prefix, string.Empty));
var propValue = prop.GetValue(vm);
return propValue as string ?? string.Empty;
}
else
{
return textProvider.GetText(name, str);
}
});
return string.Join(", ", appliedStrings);
}
else
{
return textProvider.GetText(name, keyString);
}
case "Hint":
var appliedText = textProvider.GetText(name, keyString);
return $"Double tap to {appliedText}";
default:
break;
}
}
return string.Empty;
}
}
Ultimately landed on this solution after realizing that the IMarkupExtension class is triggered BEFORE the ViewModel has set its properties.
[ContentProperty(nameof(Values))]
public class Provider : IMarkupExtension<MultiBinding>
{
readonly static IMvxTextProvider _textProvider = Mvx.IoCProvider.Resolve<IMvxTextProvider>();
public string Values { set; get; }
IList<BindingBase> Bindings { get; set; } = new List<BindingBase>();
string StringFormat { get; set; } = "{0}";
object IMarkupExtension.ProvideValue(IServiceProvider serviceProvider) => ProvideValue(serviceProvider);
public MultiBinding ProvideValue(IServiceProvider serviceProvider)
{
var valueProvider = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
var _property = valueProvider?.TargetProperty as BindableProperty;
object rootObject = null;
var propertyInfo = valueProvider.GetType()
.GetTypeInfo()
.DeclaredProperties
.FirstOrDefault(dp => dp.Name.Contains("ParentObjects"));
var parentObjects = (propertyInfo.GetValue(valueProvider) as IEnumerable<object>).ToList();
rootObject = parentObjects.Last();
var name = string.Empty;
var page = (VisualElement)rootObject;
name = page.GetType().BaseType.GetGenericArguments()[0].Name;
if (!string.IsNullOrEmpty(name))
{
var propertyName = _property.PropertyName;
if (SemanticPropertyCheck(_property, propertyName))
{
BuildBindings(propertyName, name, Values);
}
else
{
Bindings.Add(new Binding()
{
Path = $"[{name}|{Values}]",
Source = InternalValue.Instance
});
}
}
return new MultiBinding()
{
Bindings = Bindings,
StringFormat = StringFormat
};
}
bool SemanticPropertyCheck(BindableProperty property, string name) =>
property.DeclaringType.Name.Equals("SemanticEffect") && (name.Equals("Description") || name.Equals("Hint"));
void BuildBindings(string propertyName, string name, string valueString)
{
if (!string.IsNullOrEmpty(valueString) && !string.IsNullOrEmpty(propertyName))
{
switch (propertyName)
{
case "Description":
if (valueString.Contains('|'))
{
var values = (valueString.Split(new char[] { '|' }) as IEnumerable<string>).ToList();
values.ForEach(s =>
{
var index = values.IndexOf(s);
Bindings.Add(CreateBinding(name, s.Trim(), false));
if (index > 0)
StringFormat += $", {{{index}}}";
});
}
else
{
Bindings.Add(CreateBinding(name, valueString, false));
}
break;
case "Hint":
Bindings.Add(CreateBinding(name, valueString, true));
break;
default:
break;
}
}
}
BindingBase CreateBinding(string name, string key, bool isHint)
{
var prefix = "ViewModel.";
return (key.Contains(prefix))
? new Binding() { Path = key.TrimStart(prefix.ToCharArray()) }
: new Binding() { Path = $"[{name}|{key}]", Source = InternalValue.Instance };
}
sealed class InternalValue
{
readonly static IMvxTextProvider _textProvider = Provider._textProvider;
public static InternalValue Instance { get; } = new InternalValue();
public static InternalValue HintInstance { get; } = new InternalValue() { _isHint = true };
bool _isHint { get; set; } = false;
public string this[string _nameKey] => GetText(_nameKey.Split('|'));
private string GetText(string[] nameKey)
{
var name = nameKey[0];
var key = nameKey[1];
var prefix = _isHint
? "Double tap to "
: string.Empty;
var appliedText = _textProvider.GetText(name, key);
return $"{prefix}{appliedText}";
}
}
}
I made an application to download files into a folder inside another folder.
The name for the folder obtained from DataFile name from database and match the name of the image that has been downloaded.
I'm having a problem, that when downloading to a folder for the first bundle of data is fine, but at the time of downloading the data bundle again the previous folder and the new folder also download both files.
When downloading the files that differ it will create a new folder again and the two previous folders are also downloaded the file. For more details, can see in the image below:
And should one folder contains two files.
JSON:
RHData Class:
[PrimaryKey]
public string SKU { get; set; }
public string Judul { get; set; }
public string Tipe { get; set; }
public string Harga { get; set; }
public string Gratis { get; set; }
public string DataFile { get; set; }
RHViewModel class:
class RHViewModel
{
private string sku = string.Empty;
public string SKU
{
get { return sku; }
set
{
if (sku == value)
return;
sku = value;
RaisePropertyChanged("SKU");
}
}
private string judul = string.Empty;
public string Judul
{
get { return judul; }
set
{
if (judul == value)
return;
judul = value;
RaisePropertyChanged("Judul");
}
}
private string tipe = string.Empty;
public string Tipe
{
get { return tipe; }
set
{
if (tipe == value)
return;
tipe = value;
RaisePropertyChanged("Tipe");
}
}
private string harga = string.Empty;
public string Harga
{
get { return harga; }
set
{
if (harga == value)
return;
harga = value;
RaisePropertyChanged("Harga");
}
}
private string cover = string.Empty;
private string gratis = string.Empty;
public string Gratis
{
get { return gratis; }
set
{
if (gratis == value)
return;
gratis = value;
RaisePropertyChanged("Gratis");
}
}
private string dataFile = string.Empty;
public string DataFile
{
get { return dataFile; }
set
{
if (dataFile == value)
return;
dataFile = value;
RaisePropertyChanged("DataFile");
}
}
public RHViewModel GetItem(string itemSku)
{
var item = new RHViewModel();
using (var db = new SQLiteConnection(App.SQLITE_PLATFORM, App.DB_PATH))
{
var _item = (db.Table<RHData>().Where(
c => c.SKU == itemSku)).Single();
item.SKU = _item.SKU;
item.Judul = _item.Judul;
item.Tipe = _item.Tipe;
item.Harga = _item.Harga;
item.Gratis = _item.Gratis;
item.DataFile = _item.DataFile;
}
return item;
}
public string SaveItem(RHViewModel item)
{
string result = string.Empty;
using (var db = new SQLiteConnection(App.SQLITE_PLATFORM, App.DB_PATH))
{
try
{
var existingItem = (db.Table<RHData>().Where(
c => c.SKU == item.sku)).SingleOrDefault();
if (existingItem != null)
{
existingItem.SKU = item.SKU;
existingItem.Judul = item.Judul;
existingItem.Tipe = item.Tipe;
existingItem.Harga = item.Harga;
existingItem.Gratis = item.Gratis;
existingItem.DataFile = item.DataFile;
int success = db.Update(existingItem);
}
else
{
int success = db.Insert(new RHData()
{
SKU = item.SKU,
Judul = item.Judul,
//Deskripsi = item.Deskripsi,
Tipe = item.Tipe,
Harga = item.Harga,
Gratis = item.Gratis,
//Cover = item.Cover,
//File = item.File,
DataFile = item.DataFile
});
}
result = "Success";
}
catch
{
result = "This item was not saved.";
}
}
return result;
}
public string DeleteItem(string itemDataFile)
{
string result = string.Empty;
using (var dbConn = new SQLiteConnection(App.SQLITE_PLATFORM, App.DB_PATH))
{
var existingItem = dbConn.Query<RHData>("select * from RH where DataFile =" + itemDataFile).FirstOrDefault();
if (existingItem != null)
{
dbConn.RunInTransaction(() =>
{
dbConn.Delete(existingItem);
if (dbConn.Delete(existingItem) > 0)
{
result = "Success";
}
else
{
result = "This item was not removed";
}
});
}
return result;
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void RaisePropertyChanged(string propertyName)
{
var handler = this.PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
RHItemsViewModel Class:
class RHItemsViewModel : RHViewModel
{
private ObservableCollection<RHViewModel> items;
public ObservableCollection<RHViewModel> Items
{
get
{
return items;
}
set
{
items = value;
RaisePropertyChanged("Items");
}
}
public ObservableCollection<RHViewModel> GetItems()
{
items = new ObservableCollection<RHViewModel>();
using (var db = new SQLiteConnection(App.SQLITE_PLATFORM, App.DB_PATH))
{
var query = db.Table<RHData>().OrderBy(c => c.SKU);
foreach (var _item in query)
{
var item = new RHViewModel()
{
//SKU = _item.SKU,
SKU = _item.SKU,
Judul = _item.Judul,
//Deskripsi = _item.Deskripsi,
Tipe = _item.Tipe,
Harga = _item.Harga,
Gratis = _item.Gratis,
//Cover = _item.Cover,
//File = _item.File,
DataFile = _item.DataFile
};
items.Add(item);
}
}
return items;
}
}
}
App.Xaml.CS
public static string DB_PATH = Path.Combine(ApplicationData.Current.LocalFolder.Path, "RH.sqlite");
public static SQLite.Net.Platform.WinRT.SQLitePlatformWinRT SQLITE_PLATFORM;
public App()
{
Microsoft.ApplicationInsights.WindowsAppInitializer.InitializeAsync(
Microsoft.ApplicationInsights.WindowsCollectors.Metadata |
Microsoft.ApplicationInsights.WindowsCollectors.Session);
this.InitializeComponent();
this.Suspending += OnSuspending;
SQLITE_PLATFORM = new SQLite.Net.Platform.WinRT.SQLitePlatformWinRT();
if (!CheckFileExists("RH.sqlite").Result)
{
using (var db = new SQLiteConnection(SQLITE_PLATFORM, DB_PATH))
{
db.CreateTable<RHData>();
}
}
}
private async Task<bool> CheckFileExists(string fileName)
{
try
{
var store = await Windows.Storage.ApplicationData.Current.LocalFolder.GetFileAsync(fileName);
return true;
}
catch
{
}
return false;
}
Code:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
//GC.Collect();
BukuAudio dlList = e.Parameter as BukuAudio;
if (dlList != null)
{
Queue<DownloadOperation> downloadOperationList = new Queue<DownloadOperation>();
BackgroundDownloader downloader = new BackgroundDownloader();
DownloadProgress.Visibility = Visibility.Visible;
downloadfilename.Visibility = Visibility.Visible;
statusdownload.Visibility = Visibility.Visible;
deleteBtn.Visibility = Visibility.Collapsed;
viewBtn.Visibility = Visibility.Collapsed;
foreach (var path in dlList.BundlePath)
{
DownloadBuku(path);
for (int i = 0; i<dlList.BundlePath.Count;i++)
{
downloadfilename.Text = dlList.BundleName.ElementAt(i);
Uri uri = new Uri(path);
string filename = path.Substring(uri.LocalPath.LastIndexOf("/") + 1);
downloadfilename.Text = String.Format("Unduh '{0}'", filename);
}
}
DownloadGambar(dlList.Cover);
}
else
{
DownloadProgress.Visibility = Visibility.Collapsed;
downloadfilename.Visibility = Visibility.Collapsed;
statusdownload.Visibility = Visibility.Collapsed;
deleteBtn.Visibility = Visibility.Visible;
viewBtn.Visibility = Visibility.Visible;
}
bookAudio = e.Parameter as BookAudio;
}
private async void downloadClicked(object sender, RoutedEventArgs e)
{
Uri uri = new Uri(itemDetail.BundlePath.First());
string filename = System.IO.Path.GetFileName(uri.LocalPath);
string statustext = String.Format("Download Buku '{0}'?", itemDetail.Judul);
string sudahada = String.Format("Buku '{0}' sudah ada/sedang didownload", itemDetail.Judul);
MessageDialog messageDialog;
try
{
StorageFolder library = await ApplicationData.Current.LocalFolder.CreateFolderAsync("library", CreationCollisionOption.OpenIfExists);
var file = await library.GetFileAsync(filename);
messageDialog = new MessageDialog(sudahada, "Buku sudah ada");
messageDialog.Commands.Add(new UICommand("Library", (command) =>
{
this.Frame.Navigate(typeof(library.LibraryPage));
}));
messageDialog.Commands.Add(new UICommand("Batal", (command) =>
{
//rootPage.NotifyUser("The 'Don't install' command has been selected.", NotifyType.StatusMessage);
}));
}
catch (FileNotFoundException ex)
{
//file not exists show download dialog
// Create the message dialog and set its content and title
messageDialog = new MessageDialog(statustext, "Download");
// Add commands and set their callbacks
messageDialog.Commands.Add(new UICommand("Download", (command) =>
{
itemsViewModel = new RHItemsViewModel();
itemsViewModel.SaveItem(new RHViewModel()
{
SKU = itemDetail.SKU.ToString(),
Judul = itemDetail.Judul.ToString(),
Tipe = itemDetail.Tipe.ToString(),
Harga = itemDetail.Harga.ToString(),
Gratis = itemDetail.Gratis.ToString(),
DataFile = itemDetail.DataFile.ToString()
});
this.Frame.Navigate(typeof(library.LibraryPage), itemDetail);
}));
messageDialog.Commands.Add(new UICommand("Batal", (command) =>
{
//rootPage.NotifyUser("The 'Don't install' command has been selected.", NotifyType.StatusMessage);
}));
}
// Show the message dialog
await messageDialog.ShowAsync();
}
}
Library Page:
private async void DownloadBuku(string fileLocation)
{
itemsViewModel = new RHItemsViewModel();
items = new ObservableCollection<RHViewModel>();
using (var dbConn = new SQLiteConnection(App.SQLITE_PLATFORM, App.DB_PATH))
{
var existingItem = dbConn.Table<RHData>().OrderBy(c => c.DataFile);
if (existingItem != null)
{
foreach (var _item in existingItem)
{
var item = new RHViewModel()
{
DataFile = _item.DataFile
};
items.Add(item);
var uri = new Uri(fileLocation);
var downloader = new BackgroundDownloader();
StorageFolder library = await installedLocation.CreateFolderAsync("library", CreationCollisionOption.OpenIfExists);
StorageFolder pdf = await library.CreateFolderAsync(item.DataFile.ToString(), CreationCollisionOption.OpenIfExists);
string filename = System.IO.Path.GetFileName(uri.LocalPath);
StorageFile file = await pdf.CreateFileAsync(filename,
CreationCollisionOption.ReplaceExisting);
DownloadOperation download = downloader.CreateDownload(uri, file);
await StartDownloadAsync(download);
}
}
}
}
BukuAudio Class:
class BukuAudio
{
public string SKU { get; set; }
public string Judul { get; set; }
public string Deskripsi { get; set; }
public string Tipe { get; set; }
public string NamaTipe { get; set; }
public string Harga { get; set; }
public string Cover { get; set; }
public string File { get; set; }
public string Gratis { get; set; }
public string Tanggal { get; set; }
public string DataFile { get; set; }
public JsonArray Bundle_file { get; set; }
public List<string> BundleName { get; set; }
public List<string> BundlePath { get; set; }
}
How to handle it?
Note:
First Bundle File downloaded in the folder "bundle.24b"
Second Bundle file downloaded files in the folder "bundle.23b"
Third Bundle downloaded file in the folder "bundle.22b
Supposedly the file name "bundle.24b ....." downloaded in folder bundle.24b, the file name "bundle.23b ....." downloaded in folder bundle.23b, the file name "bundle.22b ....." downloaded in folder bundle.22b
I am using the following code and the code is working for some images is fine but most images EXIF data is not getting.
ImageMetadata imageMetadata = new ImageMetadata();
public ImageMetadata ReadEXIFMetadata(string filepath)
{
FileStream fs = new FileStream(filepath, FileMode.Open, FileAccess.Read);
System.Drawing.Image image__1 = System.Drawing.Image.FromStream(fs);
PropertyItem[] imagePropertyItems = image__1.PropertyItems;
foreach (PropertyItem pi in imagePropertyItems)
{
switch ((EXIFProperty)pi.Id)
{
case EXIFProperty.Title:
imageMetadata.Title = Encoding.Unicode.GetString(pi.Value);
break;
case EXIFProperty.Author:
imageMetadata.Author = Encoding.Unicode.GetString(pi.Value);
//imageMetadata.Author = Encoding.UTF8.GetString(pi.Value)
break;
case EXIFProperty.Keywords:
imageMetadata.Keywords = Encoding.Unicode.GetString(pi.Value);
break;
case EXIFProperty.Comments:
imageMetadata.Comments = Encoding.Unicode.GetString(pi.Value);
//imageMetadata.Comments = Encoding.UTF8.GetString(pi.Value)
break;
default:
break;
}
}
fs.Close();
return imageMetadata;
}
public enum EXIFProperty
{
Title = 40091,
Author = 40093,
Keywords = 40094,
Comments = 40092
}
public class ImageMetadata
{
private string _title = string.Empty;
private string _author = string.Empty;
private string _keywords = string.Empty;
private string _comments = string.Empty;
public ImageMetadata()
{
this._title = string.Empty;
this._author = string.Empty;
this._keywords = string.Empty;
this._comments = string.Empty;
}
public ImageMetadata(string title, string author, string keywords, string comments)
{
this._title = title;
this._author = author;
this._keywords = keywords;
this._comments = comments;
}
public string Title
{
get
{
return this._title;
}
set
{
this._title = value;
}
}
public string Author
{
get
{
return this._author;
}
set
{
this._author = value;
}
}
public string Keywords
{
get
{
return this._keywords;
}
set
{
this._keywords = value;
}
}
public string Comments
{
get
{
return this._comments;
}
set
{
this._comments = value;
}
}
}
Correct me if I am doing something wrong in the above code.please help stuck with this problem.
I'm not sure why you've created your own ImageMetaData class as .NET already has one. Try:
BitmapCreateOptions createOptions = BitmapCreateOptions.PreservePixelFormat | BitmapCreateOptions.IgnoreColorProfile;
BitmapMetadata importedMetaData = new BitmapMetadata("jpg");
using (Stream sourceStream = File.Open(fileName, FileMode.Open, FileAccess.Read))
{
BitmapDecoder sourceDecoder = BitmapDecoder.Create(sourceStream, createOptions, BitmapCacheOption.Default);
// Check source is has valid frames
if (sourceDecoder.Frames[0] != null && sourceDecoder.Frames[0].Metadata != null)
{
sourceDecoder.Frames[0].Metadata.Freeze();
// Get a clone copy of the metadata
BitmapMetadata sourceMetadata = sourceDecoder.Frames[0].Metadata.Clone() as BitmapMetadata;
importedMetaData = sourceMetadata;
}
}
return importedMetaData;
I'm trying to post a photo to Facebook using Graph API. I have managed to post a message to my timeline, but not a photo. The Facebook-debugger gives no errors and the object properties are correct.
public class oAuthFacebook
{
public enum Method { GET, POST };
public const string AUTHORIZE = "https://graph.facebook.com/oauth/authorize";
public const string ACCESS_TOKEN = "https://graph.facebook.com/oauth/access_token";
public const string CALLBACK_URL ="http://test.com/FbCallback.aspx";
private string _consumerKey = "";
private string _consumerSecret = "";
private string _token = "";
public string ConsumerKey
{
get
{
if (_consumerKey.Length == 0)
{
_consumerKey = "";
}
return _consumerKey;
}
set { _consumerKey = value; }
}
public string ConsumerSecret
{
get
{
if (_consumerSecret.Length == 0)
{
_consumerSecret = "";
}
return _consumerSecret;
}
set { _consumerSecret = value; }
}
public string Token { get { return _token; } set { _token = value; } }
public string AuthorizationLinkGet()
{
return string.Format("{0}?client_id={1}&redirect_uri={2}&,publish_actions",
AUTHORIZE, this.ConsumerKey, CALLBACK_URL);
}
public void AccessTokenGet(string authToken)
{
this.Token = authToken;
string accessTokenUrl = string.Format("{0}?client_id={1}&redirect_uri=
{2}&client_secret={3}&code={4}",
ACCESS_TOKEN, this.ConsumerKey, CALLBACK_URL, this.ConsumerSecret, authToken);
string response = WebRequest(Method.GET, accessTokenUrl, String.Empty);
if (response.Length > 0)
{
NameValueCollection qs = HttpUtility.ParseQueryString(response);
if (qs["access_token"] != null)
{
this.Token = qs["access_token"];
}
}
}
public string WebRequest(Method method, string url, string postData)
{
HttpWebRequest webRequest = null;
StreamWriter requestWriter = null;
string responseData = "";
webRequest = System.Net.WebRequest.Create(url) as HttpWebRequest;
webRequest.Method = method.ToString();
webRequest.ServicePoint.Expect100Continue = false;
webRequest.UserAgent = "http://test.com";
webRequest.Timeout = 40000;
if (method == Method.POST)
{
webRequest.ContentType = "application/x-www-form-urlencoded";
requestWriter = new StreamWriter(webRequest.GetRequestStream());
try
{
requestWriter.Write(postData);
}
catch
{
throw;
}
finally
{
requestWriter.Close();
requestWriter = null;
}
}
responseData = WebResponseGet(webRequest);
webRequest = null;
return responseData;
}
public string WebResponseGet(HttpWebRequest webRequest)
{
StreamReader responseReader = null;
string responseData = "";
try
{
responseReader = new StreamReader(webRequest.GetResponse().GetResponseStream());
responseData = responseReader.ReadToEnd();
}
catch
{
throw;
}
finally
{
webRequest.GetResponse().GetResponseStream().Close();
responseReader.Close();
responseReader = null;
}
return responseData;
}
And this is how I sent a testmessage, it works fine:
var json = oAuth.WebRequest(oAuthFacebook.Method.POST, url, "message=" +
HttpUtility.UrlEncode("Testmessage"));
I've tried for days to get it to work with a photo instead, any ideas of what I'm doing wrong?
I can suggest to look at FB C# SDK (available here or in NuGet) instead of sending raw requests. Here is my function I use to upload images to FB album (you should either know album ID or you can create it as well, or you can enumerate all the albums and get the one you need):
public static string UploadPhoto(string imageName, string albumID, string accesstoken, string photoComment = null, bool doNotPostStory = false)
{
var fbAPI = new FacebookApp(accesstoken);
var p = new FacebookMediaObject {FileName = path};
p.SetValue( <<YOUR IMAGE GOES HERE AS byte[]>>);
p.ContentType = "multipart/form-data";
var param = new Dictionary<string, object> { {"attachment", p} };
if (!string.IsNullOrEmpty(photoComment))
param.Add("message", photoComment);
// http://stackoverflow.com/questions/7340949/is-it-possible-to-upload-a-photo-to-fanpage-album-without-publishing-it
// http://developers.facebook.com/blog/post/482/
if (doNotPostStory == true)
{
param.Add("no_story", "1");
}
var result = fbAPI.Post(string.Format("http://graph.facebook.com/{0}/photos", albumID), param);
return result.ToString();
}