WebClient download many files error — Invalid URI: The URI is empty - c#

I want to download all the album artist from last.fm, and each cover was named album title.
But when start the program, I get an error: "Invalid URI: The URI is empty."
program code:
public static void GetXML()
{
string url = #"http://ws.audioscrobbler.com/2.0/?method=artist.gettopalbums&artist=radiohead&api_key=b25b959554ed76058ac220b7b2e0a026";
string albumName = String.Empty;
string coverLink = String.Empty;
int[] numArr = new int[30];
for (int x = 1; x < numArr.Length; x++)
{
numArr[x] = x;
}
XDocument xml = XDocument.Load(url);
foreach (var c in numArr)
{
var name = xml.XPathSelectElements(String.Format("//album[#rank='{0}']", c))
.Select(x => x.Element("name").Value)
.ToList();
foreach (var item in name)
{
albumName = item.ToString();
}
var covers = xml.XPathSelectElements(String.Format("//album[#rank='{0}']/image[#size='extralarge']", c))
.Select(x => x.Value)
.ToList();
foreach (var item in covers)
{
coverLink = item.ToString();
}
WebClient web = new WebClient();
web.DownloadFileCompleted += new System.ComponentModel.AsyncCompletedEventHandler(web_DownloadFileCompleted);
web.DownloadFileAsync(new Uri(coverLink), #"X:\Code\T\" + albumName + ".jpg");
}
}

You initialize your array as
for (int x = 1; x < numArr.Length; x++)
{
numArr[x] = x;
}
but never set the value numArr[0] which is used in foreach (var c in numArr) (and there is no album with rank=0).
Isn't this much more easier?
var albums = xml.Descendants("album")
.Select(a => new
{
Rank = (int)a.Attribute("rank"),
Name = a.Element("name").Value,
ImageUrl = a.XPathSelectElement("image[#size='extralarge']").Value
})
.ToList();

Related

Get duplicate Realtime Database Firebase results in Xamarin

I'm trying to build realtime chat through Realtime Database Firebase and Xamarin. However there is a problem like this, hope someone can help:
protected async void LoadChat()
{
string userid = "123456789";
var getroom = (await fc.Child("RecordsChat").OnceAsync<GetRoomChats>()).Select(x =>
new GetRoomChats
{
RoomID = x.Key
}).ToList();
List<GetRoomChats> listroomuser = new List<GetRoomChats>();
foreach (var room in getroom)
{
string str = null;
string[] strArr = null;
string roomget = room.RoomID;
str = roomget + "_";
char[] splitchar = { '_' };
strArr = str.Split(splitchar);
var getroomuser = strArr.Distinct().ToList();
foreach (var item in getroomuser)
{
if (item == userid)
{
var roomgetuser = new GetRoomChats()
{
RoomID = roomget
};
listroomuser.Add(roomgetuser);
}
}
}
if (listroomuser.Count() > 0)
{
var FirebaseClient = fc
.Child("RecordsChat")
.AsObservable<GetRoomChats>()
.Subscribe(async(dbevent) =>
{
//IteamGetRoomChats.Clear();
foreach (var room in listroomuser)
{
if (dbevent.Key == room.RoomID)
{
var lst = (await fc.Child("RecordsChat").Child(dbevent.Key).OrderByKey().LimitToLast(1).OnceAsync<MyDatabaseRecord>()).Select(x =>
new MyDatabaseRecord
{
NameUser = x.Object.NameUser,
Content = x.Object.Content,
RoomID = x.Object.RoomID,
DayCreate = x.Object.DayCreate,
AvatarUser = x.Object.AvatarUser,
sender_uid = x.Object.sender_uid,
receiver_uid = x.Object.receiver_uid,
receiver_read = x.Object.receiver_read
});
bool unread = false;
foreach (var i in lst)
{
if(i.sender_uid == userid)
{
i.Content = "You: " + i.Content;
var customerList = await apiServiceUserinfo.GetCustomersInfo(i.receiver_uid);
string nameget = customerList.NameStore;
string avatarget = customerList.AvatarStore;
i.NameUser = nameget;
i.AvatarUser = avatarget;
if (i.sender_read == true)
{
unread = false;
}
}
else
{
if (i.receiver_read == false)
{
i.BackgroundUser = "#f5f4f4";
unread = true;
}
}
var last = new GetRoomChats()
{
NameLast = i.NameUser,
ContentLast = i.Content,
RoomID = i.RoomID,
DayCreateLast = i.DayCreate,
AvatarLast = i.AvatarUser,
BackgroundUnread = i.BackgroundUser,
DotUnread = unread
};
IteamGetRoomChats.Add(last);
}
}
}
});
}
BindingContext = this;
}
In my example above, it actually gets the data. I try to check in the loop, to get the last content of the message. However, the displayed results are duplicated
Looking forward to everyone's help. Thank you!

Combine several Lists into one, GroupBy certain column, convert each Grouped result into HTML table

I am working on method that will send an email to each user. I have several lists where I am collecting information about items that should be fixed. After that I am Grouping by user and would like to send an email to each of them to take some actions.
Here is my current code:
public static void SendEmail()
{
string HTMLTableInString = "";
string PM = "";
var combined = List1
.Concat(List2)
.Concat(List3)
.Concat(List4)
.Concat(List5)
.Concat(List6)
.Concat(List7)
.Concat(List8)
.ToList();
if (combined.Any())
{
var GroupedList = combined.GroupBy(x => x.User)
.Select(grp => grp.ToList())
.ToList();
foreach (var item in GroupedList)
{
foreach (var pos in item)
{
HTMLTableInString = Other.CreateHTMLTable(GroupedList,
x => (pos.ProjectNumber, "Project number"),
x => (pos.SubProjectNumber, "Sub-project number"),
x => (pos.SubProjName, "Sub-project name"),
x => (pos.User, "User")
);
Console.WriteLine(pos.ProjectNumber + " " + pos.SubProjName + " " + pos.User);
PM = pos.User;
}
if (!string.IsNullOrWhiteSpace(PM))
{
Console.WriteLine("-------------------------------------------------------------");
Console.WriteLine(HTMLTableInString);
Console.WriteLine("-------------------------------------------------------------");
// Send an email
}
}
}
}
Currently this line produces what is expected
Console.WriteLine(pos.ProjectNumber + " " + pos.SubProjName + " " + pos.User);
However my HTML table does not look right, amount of rows is correct but they all have same values. This is because HTMLTableInString is overwritten numerous times (depends on User records). I understand where is an issue, but I am not able to figure out the right solution to this. Any suggestions?
CreateHTMLTable is a method, used to convert list into a string (=HTML table).
public static string CreateHTMLTable<T>(IEnumerable<T> list, params Func<T, (object, string)>[] fxns) // Used for generating HTML table
{
var sb = new StringBuilder();
sb.Append("<table>\n");
sb.Append("<thead>\n");
sb.Append("<tr>\n");
foreach (var fxn in fxns)
sb.Append("<th>").Append(fxn(default).Item2).AppendLine("</th>");
sb.Append("</tr>\n");
sb.Append("</thead>\n");
foreach (var item in list)
{
sb.Append("<tr>\n");
foreach (var fxn in fxns)
{
sb.Append("<td>");
sb.Append(fxn(item).Item1);
sb.Append("</td>");
}
sb.Append("\n</tr>\n");
}
sb.Append("</table>");
return sb.ToString();
}
I have figured it out, although I don't know is it the best possible solution. I have added one "intermediate" list to be created and writing to it/emptying it in loop.
public static void SendEmail()
{
string HTMLTableInString = "";
string PM = "";
List<ListDefaultStructure> ListForEmailTable = new List<ListDefaultStructure>();
var combined = List1
.Concat(List2)
.Concat(List3)
.Concat(List4)
.Concat(List5)
.Concat(List6)
.Concat(List7)
.Concat(List8)
.ToList();
if (combined.Any())
{
var GroupedList = combined.GroupBy(x => x.User)
.Select(grp => grp.ToList())
.ToList();
foreach (var item in GroupedList)
{
foreach (var pos in item)
{
ListForEmailTable.Add(new ListDefaultStructure
{
ProjectNumber = pos?.ProjectNumber,
SubProjectNumber = pos?.SubProjectNumber,
SubProjectName = pos?.SubProjectName,
User = pos?.User
});
PM = pos.User;
}
if (!string.IsNullOrWhiteSpace(PM))
{
HTMLTableInString = Other.CreateHTMLTable(GroupedList,
x => (pos.ProjectNumber, "Project number"),
x => (pos.SubProjectNumber, "Sub-project number"),
x => (pos.SubProjName, "Sub-project name"),
x => (pos.User, "User")
);
Console.WriteLine("-------------------------------------------------------------");
Console.WriteLine(HTMLTableInString);
Console.WriteLine("-------------------------------------------------------------");
// Send an email
}
}
}
}

Implementing search in mvc 4

I have a textbox where user types the string he needs to search. If the user enters only a single word string, then I am able to retrieve the correct data from database but if the user enters a multi-word string then my code fails.
I am using EntityFramework to get the data.
Here is my code to get the data using a single word string.
public ActionResult SearchResult(string search)
{
var j = objCon.Mobiles.Where(oh => oh.MobileName.Contains(search) || oh.Description.Contains(search));
List<Mobiles> prod = new List<Mobiles>();
foreach (var p in j)
{
Mobiles Mob = new Mobiles();
Mob.Description = p.Description;
Mob.ImgUrl = p.Url;
Mob.MobileName = p.MobileName;
Mob.Price = Convert.ToString(p.Price);
Mob.SlNo = p.SlNo;
prod.Add(Mob);
}
return View("~/Views/Product/Index.cshtml", prod);
}
I tried breaking the string into single word using split but could not get the correct data.
string str = null;
string[] strArr = null;
int count = 0;
str = //UserInput;
char[] splitchar = { ' ' };
strArr = str.Split(splitchar);
string str = null;
string[] strArr = null;
int count = 0;
str = search;
char[] splitchar = { ' ' };
strArr = str.Split(splitchar);
for (count = 0; count <= strArr.Length - 1; count++)
{
string i = strArr[count];
var j = objCon.Mobiles.Where(oh => oh.MobileName.Contains(i) || oh.Description.Contains(i));
//MessageBox.Show(strArr[count]);
foreach (var p in j)
{
Mobiles Mob = new Mobiles();
Mob.Description = p.Description;
Mob.ImgUrl = p.Url;
Mob.MobileName = p.MobileName;
Mob.Price = Convert.ToString(p.Price);
Mob.SlNo = p.SlNo;
prod.Add(Mob);
}
}
as I help you fix the problem - this is the final code
I Wrote an Example to Solve your Problem. Hope That You will Be Benefited From The Code.
First Create Mobile Class:
public class Mobile
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
Next Create Extension method To Check If there is Value:
public static bool ContainsAny(this string haystack, params string[] needles)
{
foreach (var needle in needles)
{
if (haystack.Contains(needle))
return true;
}
return false;
}
Finally Create Main Body Along with Test Data:
using System;
using System.Collections.Generic;
using System.Linq;
namespace StackOverFlow
{
static class Program
{
static void Main()
{
List<Mobile> mobiles = new List<Mobile>
{
new Mobile{Id = 1,Name = "samsung galaxy s3",Description = "model"},
new Mobile{Id = 2,Name = "nokia N67",Description = "nokia n96 time"},
new Mobile{Id = 3,Name = "iphone 5s",Description = "test"},
new Mobile{Id = 4,Name = "samsung galaxy packet",Description = "this time"},
new Mobile{Id = 5,Name = "iphone ipad",Description = "now"},
new Mobile{Id = 6,Name = "glx c5",Description = "time"},
};
string[] search = "galaxy time 5s".Split(' ');
var result = mobiles.Where(c => c.Name.ContainsAny(search) ||
c.Description.ContainsAny(search)).ToList();
foreach (var item in result)
{
Console.WriteLine(item.Id + "-" + item.Name + "-" + item.Description);
}
Console.ReadKey();
}

Compare two lists of same type

I need to compare two lists of same type. Assume I have CurrentSC List(Current modified data by user) and PreviousSC List(Saved data from database) of below class.
public class SoftClose
{
private int AID = -1;
private bool _softCloseInd;
private bool _softCloseEditInd;
private string _softClosedBy;
private DateTime _softClosedDate;
private ReferenceEnums.ActionStatus _status = ReferenceEnums.ActionStatus.NO_CHANGE;
}
public static void TPostProcessAddRemoveSoftCloseStopPaymentPrefixes(IFPMServiceInternal fpmService, AgreementRevision revision)
{
List<SoftClose> psc = null;
List<SoftClose> csc = null;
string fanValue = revision.Agreement.FAN;
psc = fpmService.GetSoftCloseByFAN(fanValue);
if (psc != null)
{
//var currentprefixes = revision.Details.Where(x => x.Prefix != null).Select(y => y.Prefix).Distinct();
//Create current SoftClose object using revision object
foreach (var prefix in revision.Details.Where(x => x.Prefix != null).Select(y => y.Prefix).Distinct())
{
var newSF =
new SoftClose
{
Id = -1,
Status = ReferenceEnums.ActionStatus.NO_CHANGE,
AgreementRevId = revision.Id,
AgreementId = revision.Agreement.Id,
WorkflowStatus = revision.WorkflowStatus,
FAN = revision.Agreement.FAN,
PID = (int)revision.Agreement.PID,
Prefix = prefix
};
csc.Add(newSF);
}
//Now you have previous and current softcloses to compare prefixes...
psc.OrderBy(x => x.Prefix.Id);
csc.OrderBy(x => x.Prefix.Id);
for(int i = 0; i < csc.Count; i++)
{
}
}
}
Lets say I have changed D3 value in PreviousSC to D2 in CurrentSC. Now i need to delete D3 value from database(As D2 value already there in database i don't need to insert) and chnage _status to DELETE and I added D4 value in CurrentSC which is not there is PreviousSC. Now I need to add D4 value in database and assign _softCloseInd and _softCloseEditInd to Y and change _status to ADD.
How to achieve this in best way?
class Program
{
static void Main(string[] args)
{
List<SoftClose> psc = new List<SoftClose>(){
new SoftClose(){ID=1, Status = "NO_CHANGE",AID=19, Prefix = "D1"},
new SoftClose(){ID=2, Status = "NO_CHANGE",AID=20, Prefix = "D2"},
new SoftClose(){ID=3, Status = "NO_CHANGE",AID=21, Prefix = "D3"},
new SoftClose(){ID=3, Status = "NO_CHANGE",AID=22, Prefix = "D9"}
};
List<SoftClose> csc = new List<SoftClose>(){
new SoftClose(){ID=-1, Status = "NO_CHANGE",AID=19, Prefix = "D2"},
new SoftClose(){ID=-1, Status = "NO_CHANGE",AID=20, Prefix = "D2"},
new SoftClose(){ID=-1, Status = "NO_CHANGE",AID=21, Prefix = "D6"},
new SoftClose(){ID=-1, Status = "NO_CHANGE",AID=22, Prefix = "D4"},
new SoftClose(){ID=-1, Status = "NO_CHANGE",AID=23, Prefix = "D5"},
new SoftClose(){ID=-1, Status = "NO_CHANGE",AID=24, Prefix = "D3"}
};
List<SoftClose> esc = new List<SoftClose>();
Console.WriteLine("---------Previous List----------");
foreach (var item in psc)
{
Console.WriteLine($"Id:{item.ID}, Desc1:{item.Prefix}, Status:{item.Status}");
}
Console.WriteLine("--------------------------------------");
Console.WriteLine("---------Current List----------");
foreach (var item in csc)
{
Console.WriteLine($"Id:{item.ID}, Desc1:{item.Prefix}, Status:{item.Status}");
}
Console.WriteLine("--------------------------------------");
var addlist = csc.Where(c => psc.All(p => !p.Prefix.Equals(c.Prefix)));
foreach (var n in addlist)
{
var index = csc.FindIndex(p => p.Prefix.Equals(n.Prefix));
csc[index].Status = "ADD";
esc.Add(csc[index]);
}
var deletelist = psc.Where(p => p.Status.Equals("NO_CHANGE") && !csc.Exists(c => c.Prefix.Equals(p.Prefix)));
foreach (var n in deletelist)
{
var index = psc.FindIndex(c => c.Prefix.Equals(n.Prefix));
if (psc.FindIndex(c => c.Prefix.Equals(n.Prefix)) >= 0)
{
psc[index].Status = "REMOVE";
esc.Add(psc[index]);
}
}
Console.WriteLine("---------Effective List----------");
foreach (var item in esc)
{
Console.WriteLine($"Id:{item.ID}, Prefix:{item.Prefix}, Status:{item.Status}");
}
Console.ReadLine();
}
}
public class SoftClose
{
public int ID = -1;
public int AID = -1;
public int WFID = -1;
public string Prefix;
public DateTime SCDATE;
public string Status;
}

How to get the first N result from google search using C#?

How to get the first N result from google search using c#?
using (var webclient = new WebClient())
{
const string url = "https://www.google.com.au/search?num=100&q=my+search+term";
var result = webclient.DownloadString(url);
}
Update:
How can I get where and how many times a specific url appeared ?
The following will return the first 100 result of searching 'my search term' and return the order of a specified target 'mytarget'
internal class Program
{
private const string Url = "http://www.google.com/search?num=100&q=my+search+term";
private static void Main(string[] args)
{
var result = new HtmlWeb().Load(Url);
var nodes = result.DocumentNode.SelectNodes("//html//body//div[#class='g']");
var indexes = nodes == null
? new List<int> { 0 }
: nodes.Select((x, i) => new { i, x.InnerHtml })
.Where(x => x.InnerHtml.Contains("mytarget"))
.Select(x => x.i + 1)
.ToList();
Console.WriteLine(String.Join(", ", indexes));
Console.ReadLine();
}
}
another way to do it using regex:
string html;
using (var webClient = new WebClient())
{
html = webClient.DownloadString(searchUrl);
}
var regex = new Regex("<div class=\"g\">(.*?)</div>");
var matches = regex.Matches(html).Cast<Match>().ToList();
var indexes = matches.Select((x, i) => new { i, x })
.Where(x => x.ToString().Contains("mytarget"))
.Select(x => x.i + 1)
.ToList();

Categories

Resources