I wanted to write a Page parser for VK.com. My Problem is, that the page source contains only 50 Results, and the others are reloaded after reaching the end of the Page.
My Code until now:
private void syncToolStripMenuItem_Click(object sender, EventArgs e)
{
string[] information, title, artist;
int i = 0;
List<string> joint = new List<string>();
information = info_basic(webBrowser1.DocumentText);
title = info_title(information);
artist = info_artist(information);
foreach (string str in title)
{
joint.Add(artist[i] + " - " + title[i]);
i++;
}
listBox1.Items.Clear();
listBox1.Items.AddRange(joint.ToArray());
}
private string[] info_basic(string source)
{
string[] temps;
List<string> sub = new List<string>();
temps = Regex.Split(source, "<div class=\"play_btn fl_l\">");
foreach (string str in temps)
{
sub.Add(str);
}
sub.RemoveRange(0, 1);
return sub.ToArray();
}
Important Code of Page:
http://csharp.bplaced.net/files/vk%20source.txt
I recommend to monitor traffic from page to vk.com when you scroll to the bottom
(for example, using fiddler http proxy), and find out how page is dynamically loaded.
Most probably this is done through ajax async calls from javascript.
And then, simulate same behavior in code to load entire page. HttpWebRequest class would work best for this task.
But since you are using webBrowser control, and probably it does all the work for loading the content - you can try to programmatically scroll the web browser control view, so that native js would fire and load content, stop when you reach the bottom, and then parse entire loaded page.
Related
Greeting of the day everyone.
Hoping you are all well. I need your help to solve a simple issue ( I an new to C# + ASP.net).
I have created a ASp.net portal. When a user open that portal (web page). the Webpage give him a list of Groups whose he is the member of and the list of group whose he can add to himself..
It also contain two Drop Downs. One contains the list of groups, whose use can add to themselves. The second one contains the list of groups , whose the user is member of, and he can remove it from those groups.
Adding and removing code is working fine. But I have to refresh the page manually to show the updated information. After clicking the Add or Remove Button page is not refreshing with the updated information.
I tried to use redirected to main page using Response.Redirect("Success.aspx")
But nothing working,
protected void Page_Load(object sender, EventArgs e)
{
string uN = "domain\\michael.jackson";
//SystemResources sr = new SystemResources();
//ActiveUser usr = sr.GetUserDetails(uN).FirstOrDefault();
LabelUserName.Text = "michael.jackson";
// Getting the list of groups using of praticular OU the classOrgUnitGroup
string sdomain = ClassGroupPortalSettings.getDomainName();
string sInterstOU = "OU=testing,DC=analysys,DC=com";
classOrgUnitGroup a = new classOrgUnitGroup();
List<string> allGroups = a.GetGroupFromOu(sdomain, sInterstOU);
string grouplist = "<ul>";
foreach (string group in allGroups)
{
grouplist = grouplist + "<li><a href='showgroupmembers.aspx?group=" + group + "'>" + group + "</a></li>";
}
grouplist = grouplist + "</ul>";
lblOpenGroups.Text = grouplist;
//// 4. Finding users group membership.
string sDomain = ClassGroupPortalSettings.getDomainName();
classUserGroupMembership myMembership = new classUserGroupMembership();
List<string> myGroupsMem = myMembership.getMyGroupMembership(sDomain, "domain\\michael.jackson");
string glList = "<ul>";
string openlList = "<ul>";
string otherGroup = "<ul>";
foreach (string grp in myGroupsMem)
{
//BulletedListMyGroups.Items.Add(grp);
glList = glList + "<li>" + grp + "</li>";
if (allGroups.Contains(grp))
{
DropDownListMyGroups.Items.Add(grp);
openlList = openlList + "<li>" + grp + "</li>";
}
else
{
otherGroup = otherGroup + "<li>" + grp + "</li>";
}
}
glList = glList + "</ul>";
openlList = openlList + "</ul>";
otherGroup = otherGroup + "</ul>";
LabelOtherGrp.Text = otherGroup;
LabelOpenGrp.Text = openlList;
// LabelMyGroup.Text = glList;
foreach (string emailGroup in allGroups)
{
if (!myGroupsMem.Contains(emailGroup))
{
DropDownListOpenGroups.Items.Add(emailGroup);
}
}
}
This is code which run when a page reload.
The issue is : When I click on Remove Button or Add Button, it run the code to add or remove user from selected group. when page reload after clicking on button. The Group membership labels. and Dropdown box is not updating with code :(
I'm assuming your scenario like this, you're having two Drop down. One is full of records and the items can be select. Once items are selected, user will submit the button then records will save into database/xml. Later you're retrieving the items from db/xml and showing that in second Drop down.
Now you're issue is that the records are not showing in second Drop down after clicking the submit button,
If it so, you have two options.
1) You can pull your records as soon as insert things made into db.
2) You can pull your records in Page load itself as I mentioned below,
If(Postback) // Or If(PostBack == true)
{
// Pull your records and display in Drop down.
}
It is just the order of events which causing confusion IMO. Page_Load is called first and then control events(click, change etc). So on add/delete you need to rebind the items.
https://msdn.microsoft.com/en-gb/library/ms178472%28v=vs.100%29.aspx
Move out the data bind logic to a function and call function at the end of click event as well. Then you can reuse the function in page load and put logic to bind in page load only of its not postback because you might be rebinding unnecessarily in page load.
protected void Page_Load(object sender, EventArgs args)
{
if(!IsPostBack)
{
DataBindLogic();
}
}
private void DataBindLogic()
{
/*Put databind code here */
}
protected void RemoveBtn_Click(Object sender,Eventargs args)
{
/*Do db update */
DataBindLogic();
}
Thanks a lot everyone and and each of you for your time and help and energy, thanks a ton.
The issue is resolved, I have added another lines of code in the Postback, which checks the action of the User.
For example, if used Remove from the Group,
Then get the name of the Group and use action REMOVE
Then Update the DropDown box and Current membership box.
I did the same for the add group too, and it resolved the issue for me.
Thanks again , and whishing you a great day ahead.
Regards and Best wishes
Aman
I'm trying to simply select one string line out a long list strings that are held on a server and seperated with a pipe character. This string is grabbed by a php script and the string line is a list of all the media and folders I have on my server.
In my code I'm getting this information and returning it with the following code:
using (var client = new WebClient())
{
result = client.DownloadString("http://server.foo.com/images/getDirectoryList.php");
}
textBox1.Text = string.Join(Environment.NewLine, result.Split('|'));
And it looks like this:
But when I try to simply click on one of them, my cursor simply just goes to where I've clicked. Like this, I tried to select md-harrier.jpg and my cursor just ends up at the end of jpg:
What I'm really wanting is pictured below. I click on Koala.jpg and the whole thing is highlighted and I have the ability to store the name of what it is I've just clicked on. TO achieve that screen shot I had to click next to Koala.jpg and then drag my mouse along.
Is there anyway I can achieve what I want to achieve?
The key thing to note about this is that I will have no idea how many files will be on the server, nor what they will be called. My php script is grabbing this information and displaying it in my winform text box using the code I have wrote above.
as Simon said you need a ListBox, a ListBox fits here because it allows you to select a line, and you can register to the event of SelectedIndexChanged and store the name that was selected.
to initiate the values do
using (var client = new WebClient())
{
result = client.DownloadString("http://bender.holovis.com/images/getDirectoryList.php");
}
listBox1.Items.AddRange(result.Split('|'));
listBox1.SelectedIndexChanged += new System.EventHandler(this.listBox1_SelectedIndexChanged);
and on the selectedItemChanged:
string currVal;
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
currVal = (string)listBox1.SelectedItem;
}
As you said you have no reason to use TextBox,then by using ListBox you can achieve that in this way;
using (var client = new WebClient())
{
result = client.DownloadString("http://bender.holovis.com/images/getDirectoryList.php");
}
string[] names=result.Split('|');
foreach(string name in names)
{
if(name!="|"&&name!=" ")
{
listbox.Items.Add(name);
}
}
Additionally,if you would like to store selected item in a variable subscribe to ListBox's SelectionChangedEvent and store the selection index in a variable in this way;
int selection=;
private void ListBox1_SelectionIndexChanged(object sender,EventArgs e)
{
selection=ListBox1.SelectedIndex;
}
I am new to .Net platform and I am stuck in retrieving controls from .aspx pages since two days.
I am trying to get all the controls from all the .aspx pages in my website.
So for that I create the object of the Page from the string of class name which I get from my database. I have already stored the class names of .aspx.cs files in database
The code in C# is:
Page obj = (Page)Activator.CreateInstance(null, string ClassName).Unwrap();
The string "ClassName" is taken from the database.
Now during Debug time I can see that there are controls in the obj but I get 0 in controls.count. I guess this is because the controls are still not initialized.
Image 1 during debug time:
Image 2 during debug time showing my controls
My code looks like this.
Page obj = (Page)Activator.CreateInstance(null, string ClassName).Unwrap()
List<string[]> fieldsNotInDB = GetControlCollections(obj)
This is my function to get all the controls from the Page obj
public List<string[]> GetControlCollections(Page p)
{
List<string[]> controlList = new List<string[]>();
IterateControls(p.Controls, controlList);
return controlList;
}
public void IterateControls(System.Web.UI.ControlCollection page, List<string[]> controlList)
{
foreach (System.Web.UI.Control c in page)
{
if (c.ID != null)
{
string []s=new string[2];
s[0]=c.ID;
s[1]=c.GetType().ToString();
controlList.Add(s);
}
if (c.HasControls())
{
IterateControls(c.Controls, controlList);
}
}
}
How do I get the Controls from my obj?
You are missing a fundamental point of asp.net : the page lifecycle.
Here, you are creating an instance of your page object, and it's the time where the collection are initialised.
But in a real asp.net webforms website, when you reach a page, the asp.net pipeline not only create the instance, but it will also launch a several events attached to the pages (see http://msdn.microsoft.com/en-us/library/ms178472(v=vs.100).aspx)
In fact, the controls of yours page will not be available before the init event.
I am developing a very simple application that parses an XML feed, does some formatting and then displays it in a TextBlock. I've added a hyperLink (called "More..) to the bottom of the page (ideally this would be added to the end of the TextBlock after the XML has been parsed) to add more content by changing the URL of the XML feed to the next page.
The issue I'm experiencing is an odd one as the program works perfectly when in the Windows Phone 7 Emulator, but when I deploy it to the device or debug on the device, it works for the first click of the "More..." button, but the ones after the first click just seem to add empty space into the application when deployed or debugged from the device.
I'm using a Samsung Focus (NoDo) and originally thought this may have had to do with the fact that I may not have had the latest developer tools. I've made sure that I am running the latest version of Visual Studio and am still running into the issue.
Here are some snippets of my code to help out.
I've declared the clickCount variable here:
public partial class MainPage : PhoneApplicationPage
//set clickCount to 2 for second page
int clickCount = 2;
Here is the snippet of code I use to parse the XML file:
void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error == null)
{
ListBoxItem areaItem = null;
StringReader stream = new StringReader(e.Result);
XmlReader reader = XmlReader.Create(stream);
string areaName = String.Empty;
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element)
{
if (reader.Name == "example")
{
areaName = reader.ReadElementContentAsString();
areaItem = new ListBoxItem();
areaItem.Content = areaName;
textBlock1.Inlines.Add(areaName);
textBlock1.Inlines.Add(new LineBreak());
}
}
}
}
}
and the code for when the hyperLink button is clicked:
private void hyperlinkButton1_Click(object sender, RoutedEventArgs e)
{
int stringNum = clickCount;
//URL is being incremented each time hyperlink is clicked
string baseURL = "http://startofURL" + stringNum + ".xml";
Uri url = new Uri(baseURL, UriKind.Absolute);
WebClient client = new WebClient();
client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted);
client.DownloadStringAsync(url);
//increment page number
clickCount = clickCount + 1;
}
It feels like there's a little more debugging to do here.
Can you test where exactly this is going wrong?
is it the click that is not working on subsequent attempts?
is it the HTTP load which is failing?
is it the adding of inline text which is failing?
Looking at it, I suspect it's the last thing. Can you check that your TextBlock is expecting Multiline text? Also, given what you've written (where you don't really seem to be making use of the Inline's from the code snippet I've seen), it might be easier to append add the new content to a ListBox or a StackPanel rather than to the inside of the TextBlock - ListBox's especially have some benefit in terms of Virtualizing the display of their content.
How to call a javascript function inside server side after the code is executed in page load/any events ? I am using UpdatePanel in this page. I had tried Page.RegisterStartUpScript, ClientScript.RegisterStartupScript. None of this works.
With an UpdatePanel you need to use ScriptManager.RegisterStartupScript, like this:
var script = "alert('hi);";
ScriptManager.RegisterStartupScript(this, GetType(), "MyScript", script, true);
You have to remember in an UpdatePanel, you're not sending the whole page back to the client, so the Page versions won't work, because their content never goes anywhere on a partial update. With ScriptManager it actively shoves this into the AJAX response it's sending as a script to execute, so it's behaving a little differently.
Just yesterday I did some research to help a fellow co-worker out and came up with the following solution. It relys on some techniques used in ajax control extenders in the use of registering data items. Since I wanted this to be more of a generic approach, I placed the following code in a script block in the master page just after the scriptmanager object:
Sys.WebForms.PageRequestManager.getInstance().add_pageLoading(PageLoadingHandler);
function PageLoadingHandler(sender, args) {
var dataItems = args.get_dataItems();
if ($get('<%=JSBridge.ClientID%>') !== null) {
eval(dataItems['<%=JSBridge.ClientID%>']);
}
}
Then somewhere in the markup of the master page I placed a hiddenfield as in:
asp:HiddenField ID="JSBridge" runat="server"
That's it for the master page. Now, all of my webpages inherit from a base page so I placed a method in the base page as in:
public void InvokeScriptMethod(string methodName, string[] methodArgs)
{
string sArgs = string.Empty;
string delim = string.Empty;
bool isNumeric = false;
int iArg = 0;
if (methodArgs != null && methodArgs.Length > 0)
{
foreach (string arg in methodArgs)
{
isNumeric = int.TryParse(arg, out iArg);
sArgs += delim + ((isNumeric) ? arg : "'" + arg + "'");
delim = ",";
}
}
ScriptManager manager = (ScriptManager)Master.FindControl("ScriptManager1");
if (manager.IsInAsyncPostBack)
{
manager.RegisterDataItem(Master.FindControl("JSBridge"), methodName + "(" + sArgs + ")");
}
}
So, assuming your content is inside an update panel, any button clicks or any event for that matter, on any web page, you can simply do the following:
protected void MyButton_Click(object sender, EventArgs e)
{
//-- Call base page method to invoke javascript call
InvokeScriptMethod("ShowMessage", new string[] { "David", "Whitten", "44" });
}
This is assuming you have a javascript method out there somewhere called "ShowMessage" with the necessary parameters. Obviously, one can specify any method name and any numbers of parameters.
Just wanted to share my findings. Maybe there is even a better way but I find this pretty simple and flexible.
David
ScriptManager.RegisterStartupScript
Registers a startup script block for a
control that is inside an UpdatePanel
by using the ScriptManager control,
and adds the script block to the page.