This sample code for the Bing Maps REST Services Toolkit uses a delegate to get the response and then outputs a message from within the delegate method. However, it does not demonstrate how to access the response from outside of the invocation of GetResponse. I cannot figure out how to return a value from this delegate. In other words, let us say I want to use the value of the longitude variable right before the line Console.ReadLine(); How do I access that variable in that scope?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BingMapsRESTToolkit;
using System.Configuration;
using System.Net;
using System.Runtime.Serialization.Json;
namespace RESTToolkitTestConsoleApp
{
class Program
{
static private string _ApiKey = System.Configuration.ConfigurationManager.AppSettings.Get("BingMapsKey");
static void Main(string[] args)
{
string query = "1 Microsoft Way, Redmond, WA";
Uri geocodeRequest = new Uri(string.Format("http://dev.virtualearth.net/REST/v1/Locations?q={0}&key={1}", query, _ApiKey));
GetResponse(geocodeRequest, (x) =>
{
Console.WriteLine(x.ResourceSets[0].Resources.Length + " result(s) found.");
decimal latitude = (decimal)((Location)x.ResourceSets[0].Resources[0]).Point.Coordinates[0];
decimal longitude = (decimal)((Location)x.ResourceSets[0].Resources[0]).Point.Coordinates[1];
Console.WriteLine("Latitude: " + latitude);
Console.WriteLine("Longitude: " + longitude);
});
Console.ReadLine();
}
private static void GetResponse(Uri uri, Action<Response> callback)
{
WebClient wc = new WebClient();
wc.OpenReadCompleted += (o, a) =>
{
if (callback != null)
{
// Requires a reference to System.Runtime.Serialization
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Response));
callback(ser.ReadObject(a.Result) as Response);
}
};
wc.OpenReadAsync(uri);
}
}
}
For the provided example AutoResetEvent class could be utilized to control the flow, in particular to wait asynchronous WebClient.OpenReadCompleted Event is completed like this:
class Program
{
private static readonly string ApiKey = System.Configuration.ConfigurationManager.AppSettings.Get("BingMapsKey");
private static readonly AutoResetEvent StopWaitHandle = new AutoResetEvent(false);
public static void Main()
{
var query = "1 Microsoft Way, Redmond, WA";
BingMapsRESTToolkit.Location result = null;
Uri geocodeRequest = new Uri(string.Format("http://dev.virtualearth.net/REST/v1/Locations?q={0}&key={1}",
query, ApiKey));
GetResponse(geocodeRequest, (x) =>
{
if (response != null &&
response.ResourceSets != null &&
response.ResourceSets.Length > 0 &&
response.ResourceSets[0].Resources != null &&
response.ResourceSets[0].Resources.Length > 0)
{
result = response.ResourceSets[0].Resources[0] as BingMapsRESTToolkit.Location;
}
});
StopWaitHandle.WaitOne(); //wait for callback
Console.WriteLine(result.Point); //<-access result
Console.ReadLine();
}
private static void GetResponse(Uri uri, Action<Response> callback)
{
var wc = new WebClient();
wc.OpenReadCompleted += (o, a) =>
{
if (callback != null)
{
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Response));
callback(ser.ReadObject(a.Result) as Response);
}
StopWaitHandle.Set(); //signal the wait handle
};
wc.OpenReadAsync(uri);
}
}
Option 2
Or to switch to ServiceManager class that makes it easy when working via asynchronous programming model:
public static void Main()
{
var task = ExecuteQuery("1 Microsoft Way, Redmond, WA");
task.Wait();
Console.WriteLine(task.Result);
Console.ReadLine();
}
where
public static async Task<BingMapsRESTToolkit.Location> ExecuteQuery(string queryText)
{
//Create a request.
var request = new GeocodeRequest()
{
Query = queryText,
MaxResults = 1,
BingMapsKey = ApiKey
};
//Process the request by using the ServiceManager.
var response = await request.Execute();
if (response != null &&
response.ResourceSets != null &&
response.ResourceSets.Length > 0 &&
response.ResourceSets[0].Resources != null &&
response.ResourceSets[0].Resources.Length > 0)
{
return response.ResourceSets[0].Resources[0] as BingMapsRESTToolkit.Location;
}
return null;
}
Related
I have a program that needs to scan for other devices running my program on the network. The solution I came up with was to call each ipAddress to see if my program is running.
The code below is completely blocking the cpu:-
using Newtonsoft.Json;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace FileWire
{
class SearchNearby
{
private bool pc_search_cancelled = false;
private SynchronizedCollection<Thread> PCSearchThreadList;
private ConcurrentDictionary<String, String> NearbyPCList;
public void NewPcFound(string s, string s1)
{
Console.WriteLine(string.Format("PC Found at: {0} PC Name: {1}", s, s1));
}
public SearchNearby()
{
startPCScan();
while (true)
{
bool isAnyAlive = false;
foreach(Thread t in PCSearchThreadList)
{
isAnyAlive |= t.IsAlive;
}
if (!isAnyAlive)
{
Console.WriteLine("Search Complete");
foreach (var a in NearbyPCList)
{
Console.WriteLine(a.Key + " ;; " + a.Value);
}
startPCScan();
}
Thread.Sleep(100);
}
}
private void startPCScan()
{
PCSearchThreadList = new SynchronizedCollection<Thread>();
NearbyPCList = new ConcurrentDictionary<String, String>();
pc_search_cancelled = false;
String add = "";
System.Net.IPAddress[] ad = System.Net.Dns.GetHostByName(System.Net.Dns.GetHostName()).AddressList;
foreach (System.Net.IPAddress ip in ad)
{
add += ip.ToString() + "\n";
}
bool connected;
if (add.Trim(' ').Length == 0)
{
connected = false;
}
else
{
connected = true;
}
if (connected)
{
try
{
String[] addresses = add.Split('\n');
foreach (String address in addresses)
{
int myIP = int.Parse(address.Substring(address.LastIndexOf(".") + 1));
for (int def = 0; def <= 10; def++)
{
int finalDef = def;
for (int j = 0; j < 10; j++)
{
string finalJ = j.ToString();
Thread thread = new Thread(new ThreadStart(() =>
{
if (!pc_search_cancelled)
{
for (int i = (finalDef * 25); i < (finalDef * 25) + 25 && i <= 255; i++)
{
if (!pc_search_cancelled)
{
if (i != myIP)
{
String callToAddress = "http://" + address.Substring(0, address.LastIndexOf(".")) + "." + i + ":" + (1234 + int.Parse(finalJ)).ToString();
String name = canGetNameAndAvatar(callToAddress);
if (name != null)
{
NearbyPCList[callToAddress] = name;
NewPcFound(callToAddress, name);
}
}
}
}
}
}));
PCSearchThreadList.Add(thread);
thread.Start();
}
}
}
} catch (Exception e) {
}
}
}
private String canGetNameAndAvatar(String connection)
{
String link = connection + "/getAvatarAndName";
link = link.Replace(" ", "%20");
try
{
var client = new HttpClient();
client.Timeout = TimeSpan.FromMilliseconds(500);
var a = new Task<HttpResponseMessage>[1];
a[0] = client.GetAsync(link);
Task.WaitAll(a);
var b = a[0].Result.Content.ReadAsStringAsync();
Task.WaitAll(b);
Console.WriteLine(b.Result);
string result = b.Result;
result = result.Substring(result.IndexOf("<body>") + 6, result.IndexOf("</body>") - (result.IndexOf("<body>") + 6));
AvtarAndName json = JsonConvert.DeserializeObject<AvtarAndName>(result);
if (json != null)
{
return json.name;
}
}
catch
{
return null;
}
return null;
}
}
}
This is the exact C# version of the java code I was using in Java:-
import com.sun.istack.internal.Nullable;
import org.apache.http.*;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.HttpParams;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.URI;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
public class PCScan {
private static boolean pc_search_cancelled = false;
private static List<Thread> PCSearchThreadList;
private static HashMapWithListener<String, String> NearbyPCList;
public static void main(String[] args) {
start();
while (true) {
int numCompleted = 0;
for (Thread t : PCSearchThreadList) {
if (!t.isAlive()) {
numCompleted++;
}
}
if (numCompleted == PCSearchThreadList.size()) {
start();
}
}
}
private static void start() {
try {
startPCScan();
} catch (SocketException e) {
e.printStackTrace();
}
NearbyPCList.setPutListener(new HashMapWithListener.putListener() {
#Override
public void onPut(Object key, Object value) {
System.out.println(key.toString() + ";;" + value.toString());
}
});
}
private static void startPCScan() throws SocketException {
pc_search_cancelled = false;
PCSearchThreadList = new CopyOnWriteArrayList<>();
NearbyPCList = new HashMapWithListener<>();
Enumeration<NetworkInterface> enumeration = NetworkInterface.getNetworkInterfaces();
boolean connected;
String add = "";
while (enumeration.hasMoreElements()) {
NetworkInterface interfacea = enumeration.nextElement();
if (!interfacea.isLoopback()) {
Enumeration<InetAddress> enumeration1 = interfacea.getInetAddresses();
while (enumeration1.hasMoreElements()) {
String address = enumeration1.nextElement().getHostAddress();
if (address.split("\\.").length == 4) {
add += address + "\n";
}
}
}
}
System.out.println(add);
connected = true;
if (connected) {
try {
String[] addresses = add.split("\n");
addresses = new HashSet<String>(Arrays.asList(addresses)).toArray(new String[0]);
for (String address : addresses) {
int myIP = Integer.parseInt(address.substring(address.lastIndexOf(".") + 1));
for (int def = 0; def <= 10; def++) {
int finalDef = def;
for (int j = 0; j < 10; j++) {
int finalJ = j;
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
if (!pc_search_cancelled) {
for (int i = (finalDef * 25); i < (finalDef * 25) + 25 && i <= 255; i++) {
if (!pc_search_cancelled) {
if (i != myIP) {
String callToAddress = "http://" + address.substring(0, address.lastIndexOf(".")) + "." + i + ":" + String.valueOf(Integer.parseInt("1234") + finalJ);
String name = canGetNameAndAvatar(callToAddress);
if (name != null) {
NearbyPCList.put(callToAddress, name);
}
}
}
}
}
}
});
PCSearchThreadList.add(thread);
thread.start();
}
}
// }
// }).start();
}
} catch (Exception e) {
}
}
}
private static String canGetNameAndAvatar(String connection) {
String link = connection + "/getAvatarAndName";
link = link.replaceAll(" ", "%20");
try {
HttpClient client = new DefaultHttpClient();
HttpParams httpParams = client.getParams();
httpParams.setParameter(
CoreConnectionPNames.CONNECTION_TIMEOUT, 500);
HttpGet request = new HttpGet();
request.setURI(new URI(link));
HttpResponse response = client.execute(request);
BufferedReader in = new BufferedReader(new
InputStreamReader(response.getEntity().getContent()));
StringBuffer sb = new StringBuffer("");
String line="";
while ((line = in.readLine()) != null) {
sb.append(line);
break;
}
in.close();
String result = sb.toString();
result = result.substring(result.indexOf("<body>") + 6, result.indexOf("</body>"));
JSONObject json = new JSONObject(result);
if (json != null) {
return json.getString("name");
}
}
catch (Exception ignored){
return null;
}
return null;
}
static class HashMapWithListener<K, V> extends HashMap<K, V> {
private putListener PutListener;
public void setPutListener(putListener PutListener) {
this.PutListener = PutListener;
}
#Nullable
#Override
public V put(K key, V value) {
PutListener.onPut(key, value);
return super.put(key, value);
}
interface putListener {
public void onPut(Object key, Object value);
}
}
}
The java code runs absolutely fine and only uses about 20 percent cpu while c# code absolutely locks the PC. I tried Webclient, webrequest, httpClient. All have literally the same performance.
I need the code to be in c# as I can't include whole JRE in my program since it is too large. The rest of my program and GUI is in WPF format.
Also, I need the code to take a maximum of 50seconds while scanning ports 1234-1243. This code also works absolutely fine even on a midrange android phone. So, I don't know what the problem is.
I would suggest something like this (I've simplified it for the sake of an example):
private static HttpClient _client = new HttpClient() { Timeout = TimeSpan.FromMilliseconds(500) };
private async Task<Something> GetSomething(string url)
{
using (HttpResponseMessage response = await _client.GetAsync(url))
{
string json = await response.ReadAsStringAsync();
return JsonConvert.DeserializeObject<Something>(json);
}
}
private async Task<Something[]> GetSomethings(string[] urls)
{
IEnumerable<Task<Something>> requestTasks = urls.Select(u => GetSomething(u));
Something[] results = await Task.WhenAll<Something>(requestTasks);
return results;
}
You should also make the method calling GetSomethings async, and await it, and do the same all the way up the call chain.
async/await uses a thread pool to execute, and the thread is actually suspended while the IO part of the request occurs, meaning that no CPU time is used during this period. When then IO part is done, it resumes the code at the await.
Related information:
Asynchronous programming documentation
How and when to use 'async' and 'await'
You are using threads and multithreading completely wrong.
Because I cannot really understand what you are trying to do because everything is cramped into one function, I cannot provide you with a more detailed solution.
But let me suggest the following: I understand, you want to execute some operation in the background connecting to some other computer, try something like this
var taskList = new List<Task>();
foreach (var pc in computers)
{
var currentPcTask = Task.Run(() => DoYourWorkForSomePcHere(pc));
taskList.Add(currentPcTask);
}
Task.WaitAll(taskList.ToArray());
This will be very CPU efficient.
I am new to C# and using Task. I was trying to run this application but my application hangs every time. When I am adding task.wait(), it keeps waiting and never returns. Any help is much appreciated.
EDIT:
I want to call DownloadString Asynchronously. And when I am doing task.Start() as suggested by "Austin Salonen" I don't get the address of location but default value in location string from returnVal. It means that location got value assigned before task got completed. How can I make sure that after task is completed only then location gets assigned returnVal.
public class ReverseGeoCoding
{
static string baseUri = "http://maps.googleapis.com/maps/api/geocode/xml?latlng={0},{1}&sensor=false";
string location = "default";
static string returnVal = "defaultRet";
string latitude = "51.962146";
string longitude = "7.602304";
public string getLocation()
{
Task task = new Task(() => RetrieveFormatedAddress(latitude, longitude));
//var result = Task.Factory.StartNew(RetrieveFormatedAddress("51.962146", "7.602304"));
task.Wait();
//RetrieveFormatedAddress("51.962146", "7.602304");
location = returnVal;
return location;
}
public static void RetrieveFormatedAddress(string lat, string lng)
{
string requestUri = string.Format(baseUri, lat, lng);
using (WebClient wc = new WebClient())
{
wc.DownloadStringCompleted += new DownloadStringCompletedEventHandler(wc_DownloadStringCompleted);
wc.DownloadStringAsync(new Uri(requestUri));
}
}
static void wc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
var xmlElm = XElement.Parse(e.Result);
var status = (from elm in xmlElm.Descendants()
where elm.Name == "status"
select elm).FirstOrDefault();
if (status.Value.ToLower() == "ok")
{
var res = (from elm in xmlElm.Descendants()
where elm.Name == "formatted_address"
select elm).FirstOrDefault();
//Console.WriteLine(res.Value);
returnVal = res.Value;
}
else
{
returnVal = "No Address Found";
//Console.WriteLine("No Address Found");
}
}
}
You aren't actually running the task. Debugging and checking task.TaskStatus would show this.
// this should help
task.Start();
// ... or this:
Task.Wait(Task.Factory.StartNew(RetrieveFormatedAddress("51.962146", "7.602304")));
Though if you're blocking, why start another thread to begin with?
I don't understand why you use DownloadStringCompleted event and try to make it blocking. If you want to wait the result, just use blocking call DownloadString
var location = RetrieveFormatedAddress(51.962146, 7.602304);
string RetrieveFormatedAddress(double lat, double lon)
{
using (WebClient client = new WebClient())
{
string xml = client.DownloadString(String.Format(baseUri, lat, lon));
return ParseXml(xml);
}
}
private static string ParseXml(string xml)
{
var result = XDocument.Parse(xml)
.Descendants("formatted_address")
.FirstOrDefault();
if (result != null)
return result.Value;
else
return "No Address Found";
}
If you want to make it async
var location = await RetrieveFormatedAddressAsync(51.962146, 7.602304);
async Task<string> RetrieveFormatedAddressAsync(double lat,double lon)
{
using(HttpClient client = new HttpClient())
{
string xml = await client.GetStringAsync(String.Format(baseUri,lat,lon));
return ParseXml(xml);
}
}
When using the Lync 2010 API the LyncClient can get in the Invalid state. This occurs if for instance the Lync process is shut down.
When Lync is started again a call to Lync.GetClient() returns a Lync client reference in an Invalid state.
Reading the MSDN documentation is not very useful - the Invalid state is not described: http://msdn.microsoft.com/en-us/library/microsoft.lync.model.clientstate_di_3_uc_ocs14mreflyncclnt.aspx
My question is; how can I retrieve a Lync client reference which is not in an Invalid state?
Thanks!
The answer to my question/problem is to call the GetClient() from the same thread as it is called from the first time. This seems to never get a client in the Invalid state.
After numerous tries, I reached a not-so-pretty workaround:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Threading;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using Microsoft.Lync.Model;
using ContactAvailability = Microsoft.Lync.Controls.ContactAvailability;
namespace LyncService
{
public class MicrosoftLyncService : IMicrosoftLyncService
{
private readonly string _password = "1234";
private readonly object _syncObj = new object();
private readonly string _username = "Joe#YourCompany.com";
private volatile LyncClient _lyncClient;
public SkypeContactInfoViewModel GetSkypeContactInfo(string emailAddress)
{
try
{
lock (_syncObj)
{
Process.Start(new ProcessStartInfo
{
FileName = "taskkill",
Arguments = "/im lync.exe /f /t",
CreateNoWindow = true,
UseShellExecute = false
})?.WaitForExit();
_lyncClient = LyncClient.GetClient(true);
if (_lyncClient.State == ClientState.Uninitialized)
{
_lyncClient.BeginInitialize(ar =>
{
_lyncClient.EndInitialize(ar);
_lyncClient.StateChanged += ClientStateChanged;
},
null);
}
else
{
_lyncClient.StateChanged += ClientStateChanged;
SignIn(_username, _username, _password);
}
while (_lyncClient.State != ClientState.SignedIn)
switch (_lyncClient.State)
{
case ClientState.Invalid:
_lyncClient = LyncClient.GetClient(true);
Thread.Sleep(100);
break;
case ClientState.Uninitialized:
_lyncClient.BeginInitialize(ar =>
{
_lyncClient.EndInitialize(ar);
_lyncClient.StateChanged += ClientStateChanged;
},
null);
break;
case ClientState.SigningIn:
Thread.Sleep(100);
break;
case ClientState.SignedOut:
SignIn(_username, _username, _password);
Thread.Sleep(100);
break;
}
var contact = _lyncClient.ContactManager.GetContactByUri(emailAddress);
Thread.Sleep(1000);
var contactInfo = contact.GetContactInformation(new List<ContactInformationType>
{
ContactInformationType.Availability,
ContactInformationType.ContactEndpoints,
ContactInformationType.Title,
ContactInformationType.Company,
ContactInformationType.Department
});
return ConvertToSkypeViewModel(emailAddress, contactInfo);
}
}
catch (Exception e)
{
// Handle exception
}
}
private SkypeContactInfoViewModel ConvertToSkypeViewModel(string emailAddress,
IDictionary<ContactInformationType, object> contactInfo)
{
var result = new SkypeContactInfoViewModel();
if (contactInfo.TryGetValue(ContactInformationType.Availability, out var availability))
result.AvailabilityStatus = (ContactAvailability) availability switch
{
ContactAvailability.Invalid => Enums.ContactAvailabilityStatus.Invalid,
ContactAvailability.None => Enums.ContactAvailabilityStatus.None,
ContactAvailability.Free => Enums.ContactAvailabilityStatus.Free,
ContactAvailability.FreeIdle => Enums.ContactAvailabilityStatus.FreeIdle,
ContactAvailability.Busy => Enums.ContactAvailabilityStatus.Busy,
ContactAvailability.BusyIdle => Enums.ContactAvailabilityStatus.BusyIdle,
ContactAvailability.DoNotDisturb => Enums.ContactAvailabilityStatus.DoNotDisturb,
ContactAvailability.TemporarilyAway => Enums.ContactAvailabilityStatus.TemporarilyAway,
ContactAvailability.Away => Enums.ContactAvailabilityStatus.Away,
ContactAvailability.Offline => Enums.ContactAvailabilityStatus.Offline,
_ => Enums.ContactAvailabilityStatus.Invalid
};
if (contactInfo.TryGetValue(ContactInformationType.ContactEndpoints, out var endPoints))
((List<object>) endPoints).ForEach(endPointObject =>
{
if (endPointObject is ContactEndpoint endPoint && endPoint.Type == ContactEndpointType.WorkPhone)
result.WorkPhone = endPoint.DisplayName;
});
if (contactInfo.TryGetValue(ContactInformationType.Title, out var title)) result.JobTitle = (string) title;
if (contactInfo.TryGetValue(ContactInformationType.Company, out var company))
result.CompanyName = (string) company;
if (contactInfo.TryGetValue(ContactInformationType.Department, out var department))
result.Department = (string) department;
return result;
}
private void ClientStateChanged(object source, ClientStateChangedEventArgs data)
{
if (data.NewState != ClientState.SignedOut) return;
if (_lyncClient.InSuppressedMode)
SignIn(_username, _username, _password);
}
public void SignIn(string userUri, string domain, string password)
{
_lyncClient.CredentialRequested += CredentialRequested;
if (_lyncClient.State == ClientState.SignedOut)
_lyncClient.BeginSignIn(
userUri,
domain,
password,
callback => { _lyncClient.EndSignIn(callback); },
null);
}
private void CredentialRequested(object sender, CredentialRequestedEventArgs e)
{
if (e.Type == CredentialRequestedType.SignIn)
e.Submit(_username, _password, true);
}
}
}
How can i check if my image link is valid for both IE and FF? For example this link works just in FF, no image is displayed in IE browser. I checked the image and the color space is RGB. So image space problem is excluded.
Thanks.
Get a copy of fiddler to see the differences in response for each of the browsers. You may find that the headers are wrong and FF is correcting but IE is not.
http://www.fiddler2.com/fiddler2/
Hope this helps
Here is a class that will let you validate any kind of URI and will support multi-threaded validation of collection of URIs
using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Threading;
namespace UrlValidation
{
public class UrlValidator
{
internal static readonly Hashtable URLVerifications = new Hashtable();
internal readonly List<ManualResetEvent> Handles = new List<ManualResetEvent>();
internal void ValidateUrls()
{
var urlsToValidate = new[] { "http://www.ok12376876.com", "http//:www.ok.com", "http://www.ok.com", "http://cnn.com" };
URLVerifications.Clear();
foreach (var url in urlsToValidate)
CheckUrl(url);
if (Handles.Count > 0)
WaitHandle.WaitAll(Handles.ToArray());
foreach (DictionaryEntry verification in URLVerifications)
Console.WriteLine(verification.Value);
}
internal class RequestState
{
public WebRequest Request;
public WebResponse Response;
public ManualResetEvent Handle;
}
private void CheckUrl(string url)
{
var hashCode = url.GetHashCode();
var evt = new ManualResetEvent(false);
Handles.Add(evt);
if (!Uri.IsWellFormedUriString(url, UriKind.Absolute))
{
URLVerifications[hashCode] = "Invalid URL.";
evt.Set();
return;
}
if (!URLVerifications.ContainsKey(hashCode))
URLVerifications.Add(hashCode, null);
// Create a new webrequest to the mentioned URL.
var wreq = WebRequest.Create(url);
wreq.Timeout = 5000; // 5 seconds timeout per thread (ignored for async calls)
var state = new RequestState{ Request = wreq, Handle = evt };
// Start the Asynchronous call for response.
var asyncResult = wreq.BeginGetResponse(RespCallback, state);
ThreadPool.RegisterWaitForSingleObject(asyncResult.AsyncWaitHandle, TimeoutCallback, state, 5000, true);
}
private static void TimeoutCallback(object state, bool timedOut)
{
var reqState = (RequestState)state;
if (timedOut)
{
var hashCode = reqState.Request.RequestUri.OriginalString.GetHashCode();
URLVerifications[hashCode] = "Request timed out.";
if (reqState.Request != null)
reqState.Request.Abort();
}
}
private static void RespCallback(IAsyncResult asynchronousResult)
{
ManualResetEvent evt = null;
int hashCode = 0;
try
{
var reqState = (RequestState)asynchronousResult.AsyncState;
hashCode = reqState.Request.RequestUri.OriginalString.GetHashCode();
evt = reqState.Handle;
reqState.Response = reqState.Request.EndGetResponse(asynchronousResult);
var resp = ((HttpWebResponse)reqState.Response).StatusCode;
URLVerifications[hashCode] = resp.ToString();
}
catch (WebException e)
{
if (hashCode != 0 && string.IsNullOrEmpty((string)URLVerifications[hashCode]))
URLVerifications[hashCode] = e.Response == null ? e.Status.ToString() : (int)((HttpWebResponse)e.Response).StatusCode + ": " + ((HttpWebResponse)e.Response).StatusCode;
}
finally
{
if (evt != null)
evt.Set();
}
}
}
}
Hope that helps
I have to develop a .Net application in which i have to add or remove a user from Mailman mailing list.My Question is whether there is any .Net connector or Dll to connect to mailman mailing list using .Net.
Edit (9/21/14): I have just released a NuGet package for manipulating most aspects of a Mailman v2 list via HTTP calls. https://www.nuget.org/packages/MailmanSharp/
I'm not aware of any existing component to do this, but since the Mailman interface is all on the web, you can "control" it with HttpWebRequest; I recently wrote a small app which can retrieve the subscriber list, subscribe/unsubscribe people, and set individual flags like moderate/nomail/etc. It takes a little poking around in the source of the Mailman pages to see what variables need to be set in the POST, and some trial and error. I suggest setting up a temp Mailman list just to play with.
In order to do most of this, you'll need a persistent CookieContainer that you can hook up to your different HttpWebRequests; the first call is a POST to the admin page with the admin password to set the session cookie that gives you access to the other pages.
Some of the POSTs are regular application/x-www-form-urlencoded types, but some are also multipart/form-data. For the latter, I found some very helpful code at http://www.briangrinstead.com/blog/multipart-form-post-in-c I had to make a couple of changes so that I could pass in my CookieContainer
Here's some sample code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.Text.RegularExpressions;
using System.Data;
using System.Threading;
namespace UpdateListserv
{
class Program
{
static void Main(string[] args)
{
try
{
File.Delete(_logFilename);
Log(String.Format("Starting: {0}", DateTime.Now));
Login();
var roster = GetSubscribers();
Unsubscribe(roster);
string members = GetMemberEmails();
Subscribe(members);
Unmoderate("foo#example.com");
Log("Done");
}
catch(Exception e)
{
Log(e.Message);
}
}
private static void Unmoderate(string email)
{
Log("Unmoderating " + email);
email = email.Replace("#", "%40");
_vars.Clear();
_vars["user"] = email;
_vars[email + "_nomail"] = "off";
_vars[email + "_nodupes"] = "on";
_vars[email + "_plain"] = "on";
_vars[email + "_language"] = "en";
_vars["setmemberopts_btn"] = "Submit Your Changes";
FormUpload.MultipartFormDataPost(_adminUrl + _membersPage, "foobar", _vars, _cookies);
}
private static CookieContainer _cookies = new CookieContainer();
private static string _adminUrl = "http://mylist.com/admin.cgi/listname";
private static string _rosterUrl = "http://mylist.com/roster.cgi/listname";
private static string _pw = "myPassword";
private static string _adminEmail = "foo#example.com";
private static Dictionary<string, object> _vars = new Dictionary<string, object>();
private static string _addPage = "/members/add";
private static string _removePage = "/members/remove";
private static string _membersPage = "/members";
private static string _logFilename = "Update Listserv.log";
private static void Log(string message)
{
Console.WriteLine(message);
using (var log = File.AppendText(_logFilename))
log.WriteLine(message);
}
private static void Subscribe(string members)
{
// members is a list of email addresses separated by \n
Log("Subscribing everyone");
_vars.Clear();
_vars["subscribees"] = members;
_vars["subscribe_or_invite"] = 0;
_vars["send_welcome_msg_to_this_batch"] = 0;
_vars["send_notifications_to_list_owner"] = 0;
FormUpload.MultipartFormDataPost(_adminUrl + _addPage, "foobar", _vars, _cookies);
}
private static string GetMemberEmails()
{
// This method retrieves a list of emails to be
// subscribed from an external source
// and returns them as a string with \n in between.
}
private static void Unsubscribe(string roster)
{
// roster is a list of email addresses separated by \n
Log("Unsubscribing everybody");
_vars.Clear();
_vars["unsubscribees"] = roster;
_vars["send_unsub_ack_to_this_batch"] = 0;
_vars["send_unsub_notifications_to_list_owner"] = 0;
FormUpload.MultipartFormDataPost(_adminUrl + _removePage, "foobar", _vars, _cookies);
}
private static string GetSubscribers()
{
// returns a list of email addresses subscribed to the list,
// separated by \n
Log("Getting subscriber list");
var req = GetWebRequest(_rosterUrl);
req.Method = "post";
_vars.Clear();
_vars["roster-email"] = _adminEmail;
_vars["roster-pw"] = _pw;
var rosterLines = GetResponseString(req).Split('\n').Where(l => l.StartsWith("<li>"));
Log(String.Format("Got {0} subscribers", rosterLines.Count()));
var roster = new List<string>();
var regex = new Regex("<a.*>(.*)</a>");
foreach (var line in rosterLines)
{
roster.Add(regex.Match(line).Groups[1].Value.Replace(" at ", "#"));
}
return String.Join("\n", roster);
}
private static void Login()
{
Log("Logging in to list admin panel");
var req = GetWebRequest(_adminUrl);
req.Method = "post";
_vars["adminpw"] = _pw;
SetPostVars(req);
req.GetResponse();
}
private static HttpWebRequest GetWebRequest(string url)
{
var result = HttpWebRequest.Create(url) as HttpWebRequest;
result.AllowAutoRedirect = true;
result.CookieContainer = _cookies;
result.ContentType = "application/x-www-form-urlencoded";
return result;
}
private static string GetResponseString(HttpWebRequest req)
{
using (var res = req.GetResponse())
using (var stream = res.GetResponseStream())
using (var sr = new StreamReader(stream))
{
return sr.ReadToEnd();
}
}
private static void SetPostVars(HttpWebRequest req)
{
var list = _vars.Select(v => String.Format("{0}={1}", v.Key, v.Value));
using (var stream = req.GetRequestStream())
using (var writer = new StreamWriter(stream))
{
writer.Write(String.Join("&", list));
}
}
}
}