I am using POP3 Code for the receiving mail from mail Server It runs good on GMail and yahoo but when i am trying to connect with hotmail o ma getting error over
string response = SendCommand("STAT");
"-ERR command not expected now\r\n"
I am attaching mail code please review it and suggest me the possible solution.
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Xml;
namespace CallScreen24x7.BAL
{
public class Pop3Client : IDisposable
{
//string _host,_email,_pass;
//int port;
// string _host = ConfigurationSettings.AppSettings["host"];
public string Host { get; protected set; }
public int Port { get; protected set; }
public string Email { get; protected set; }
public string Password { get; protected set; }
public bool IsSecure { get; protected set; }
public TcpClient Client { get; protected set; }
public Stream ClientStream { get; protected set; }
public StreamWriter Writer { get; protected set; }
public StreamReader Reader { get; protected set; }
private bool disposed = false;
//public Pop3Client(string host, int port, string email, string password) : this("mail.ansitdev.com", 110, "dev#ansitdev.com", "P#ssword123", false) { }
public Pop3Client(string host, int port, string email, string password, bool secure)
{
try
{
Host = host;// ConfigurationSettings.AppSettings["host"];// "mail.ansitdev.com";
Port = port;
Email = email;// "dev#ansitdev.com";
Password = password;// ;
IsSecure = true;
}
catch (Exception ex)
{ }
}
public void Connect()
{
try
{
if (Client == null)
Client = new TcpClient();
if (!Client.Connected)
Client.Connect(Host, Port);
if (IsSecure)
{
SslStream secureStream = new SslStream(Client.GetStream());
secureStream.AuthenticateAsClient(Host);
ClientStream = secureStream;
secureStream = null;
}
else
ClientStream = Client.GetStream();
Writer = new StreamWriter(ClientStream);
Reader = new StreamReader(ClientStream);
ReadLine();
Login();
}
catch(Exception ex)
{}
}
public int GetEmailCount()
{
int count = 0;
string response = SendCommand("STAT");
if (IsResponseOk(response))
{
string[] arr = response.Substring(4).Split(' ');
count = Convert.ToInt32(arr[0]);
}
else
count = -1;
return count;
}
public Email FetchEmail(int emailId)
{
if (IsResponseOk(SendCommand("TOP " + emailId + " 0")))
return new Email(ReadLines());
else
return null;
}
public List<Email> FetchEmailList(int start, int count)
{
List<Email> emails = new List<Email>(count);
for (int i = start; i >=(start-count)+1; i--)
{
if (i >= 0)
{
Email email = FetchEmail(i);
if (email != null)
emails.Add(email);
}
}
return emails;
}
public List<MessagePart> FetchMessageParts(int emailId)
{
if (IsResponseOk(SendCommand("RETR " + emailId)))
return Util.ParseMessageParts(ReadLines());
return null;
}
public void Close()
{
try
{
if (Client != null)
{
if (Client.Connected)
Logout();
Client.Close();
Client = null;
}
if (ClientStream != null)
{
ClientStream.Close();
ClientStream = null;
}
if (Writer != null)
{
Writer.Close();
Writer = null;
}
if (Reader != null)
{
Reader.Close();
Reader = null;
}
disposed = true;
}
catch (Exception ex)
{ }
}
public void Dispose()
{
try
{
if (!disposed)
Close();
}
catch (Exception ex)
{ }
}
protected void Login()
{
try
{
if (!IsResponseOk(SendCommand("USER " + Email)) || !IsResponseOk(SendCommand("PASS " + Password))) { }
// throw new Exception("User/password not accepted");
}
catch (Exception ex)
{ }
}
protected void Logout()
{
SendCommand("RSET");
}
protected string SendCommand(string cmdtext)
{
try
{
Writer.WriteLine(cmdtext);
Writer.Flush();
return ReadLine();
}
catch (Exception ex) { return null; }
}
protected string ReadLine()
{
return Reader.ReadLine() + "\r\n";
}
protected string ReadLines()
{
StringBuilder b = new StringBuilder();
while (true)
{
string temp = ReadLine();
if (temp == ".\r\n" || temp.IndexOf("-ERR") != -1)
break;
b.Append(temp);
}
return b.ToString();
}
protected static bool IsResponseOk(string response)
{
if (response.StartsWith("+OK"))
return true;
if (response.StartsWith("-ERR"))
return false;
return true;
// throw new Exception("Cannot understand server response: " + response);
}
}
public class Email
{
public NameValueCollection Headers { get; protected set; }
public string ContentType { get; protected set; }
public DateTime UtcDateTime { get; protected set; }
public string From { get; protected set; }
public string To { get; protected set; }
public string Subject { get; protected set; }
public Email(string emailText)
{
Headers = Util.ParseHeaders(emailText);
ContentType = Headers["Content-Type"];
From = Headers["From"];
To = Headers["To"];
Subject = Headers["Subject"];
if (Headers["Date"] != null)
try
{
UtcDateTime = Util.ConvertStrToUtcDateTime(Headers["Date"]);
}
catch (FormatException)
{
UtcDateTime = DateTime.MinValue;
}
else
UtcDateTime = DateTime.MinValue;
}
}
public class MessagePart
{
public NameValueCollection Headers { get; protected set; }
public string ContentType { get; protected set; }
public string MessageText { get; protected set; }
public MessagePart(NameValueCollection headers, string messageText)
{
Headers = headers;
ContentType = Headers["Content-Type"];
MessageText = messageText;
}
}
public class Util
{
protected static Regex BoundaryRegex = new Regex("Content-Type: multipart(?:/\\S+;)" + "\\s+[^\r\n]*boundary=\"?(?<boundary>" + "[^\"\r\n]+)\"?\r\n", RegexOptions.IgnoreCase | RegexOptions.Compiled);
protected static Regex UtcDateTimeRegex = new Regex(#"^(?:\w+,\s+)?(?<day>\d+)\s+(?<month>\w+)\s+(?<year>\d+)\s+(?<hour>\d{1,2})" + #":(?<minute>\d{1,2}):(?<second>\d{1,2})\s+(?<offsetsign>\-|\+)(?<offsethours>" + #"\d{2,2})(?<offsetminutes>\d{2,2})(?:.*)$", RegexOptions.IgnoreCase | RegexOptions.Compiled);
public static NameValueCollection ParseHeaders(string headerText)
{
NameValueCollection headers = new NameValueCollection();
StringReader reader = new StringReader(headerText);
string line;
string headerName = null, headerValue;
int colonIndx;
while ((line = reader.ReadLine()) != null)
{
if (line == "")
break;
if (Char.IsLetterOrDigit(line[0]) && (colonIndx = line.IndexOf(':')) != -1)
{
headerName = line.Substring(0, colonIndx);
headerValue = line.Substring(colonIndx + 1).Trim();
headers.Add(headerName, headerValue);
}
else if (headerName != null)
headers[headerName] += " " + line.Trim();
else
throw new FormatException("Could not parse headers");
}
return headers;
}
public static List<MessagePart> ParseMessageParts(string emailText)
{
List<MessagePart> messageParts = new List<MessagePart>();
int newLinesIndx = emailText.IndexOf("\r\n\r\n");
Match m = BoundaryRegex.Match(emailText);
if (m.Index < emailText.IndexOf("\r\n\r\n") && m.Success)
{
string boundary = m.Groups["boundary"].Value;
string startingBoundary = "\r\n--" + boundary;
int startingBoundaryIndx = -1;
while (true)
{
if (startingBoundaryIndx == -1)
startingBoundaryIndx = emailText.IndexOf(startingBoundary);
if (startingBoundaryIndx != -1)
{
int nextBoundaryIndx = emailText.IndexOf(startingBoundary, startingBoundaryIndx + startingBoundary.Length);
if (nextBoundaryIndx != -1 && nextBoundaryIndx != startingBoundaryIndx)
{
string multipartMsg = emailText.Substring(startingBoundaryIndx + startingBoundary.Length, (nextBoundaryIndx - startingBoundaryIndx - startingBoundary.Length));
int headersIndx = multipartMsg.IndexOf("\r\n\r\n");
if (headersIndx == -1)
throw new FormatException("Incompatible multipart message format");
string bodyText = multipartMsg.Substring(headersIndx).Trim();
NameValueCollection headers = Util.ParseHeaders(multipartMsg.Trim());
messageParts.Add(new MessagePart(headers, bodyText));
}
else
break;
startingBoundaryIndx = nextBoundaryIndx;
}
else
break;
}
if (newLinesIndx != -1)
{
string emailBodyText = emailText.Substring(newLinesIndx + 1);
}
}
else
{
int headersIndx = emailText.IndexOf("\r\n\r\n");
if (headersIndx == -1)
throw new FormatException("Incompatible multipart message format");
string bodyText = emailText.Substring(headersIndx).Trim();
NameValueCollection headers = Util.ParseHeaders(emailText);
messageParts.Add(new MessagePart(headers, bodyText));
}
return messageParts;
}
public static DateTime ConvertStrToUtcDateTime(string str)
{
Match m = UtcDateTimeRegex.Match(str);
int day, month, year, hour, min, sec;
if (m.Success)
{
day = Convert.ToInt32(m.Groups["day"].Value);
year = Convert.ToInt32(m.Groups["year"].Value);
hour = Convert.ToInt32(m.Groups["hour"].Value);
min = Convert.ToInt32(m.Groups["minute"].Value);
sec = Convert.ToInt32(m.Groups["second"].Value);
switch (m.Groups["month"].Value)
{
case "Jan":
month = 1;
break;
case "Feb":
month = 2;
break;
case "Mar":
month = 3;
break;
case "Apr":
month = 4;
break;
case "May":
month = 5;
break;
case "Jun":
month = 6;
break;
case "Jul":
month = 7;
break;
case "Aug":
month = 8;
break;
case "Sep":
month = 9;
break;
case "Oct":
month = 10;
break;
case "Nov":
month = 11;
break;
case "Dec":
month = 12;
break;
default:
throw new FormatException("Unknown month.");
}
DateTime dt = new DateTime(year, month, day, hour, min, sec);
DateTime kt = dt.AddHours(-offsetHours);
kt = kt.AddMinutes(-offsetMinutes);
return kt;
}
throw new FormatException("Incompatible date/time string format");
}
}
}
and
int page = 1;
if (Request.QueryString["page"] == null)
{
Response.Redirect("DashBoard.aspx?page=1");
Response.Flush();
Response.End();
}
else
page = Convert.ToInt32(Request.QueryString["page"]);
try
{
Email = ConfigurationSettings.AppSettings["email"].ToString();
Password = ConfigurationSettings.AppSettings["pass"].ToString();
}
catch (Exception ex)
{
Response.Redirect("DashBoard.aspx");
objentityException.ExceptionDescription = ex.Message + " " + ex.StackTrace; ;
objentityException.MethodName = "Page_Load";
objentityException.CreatedBy = Session["UserName"].ToString();
objException.InsertException(objentityException);
}
int totalEmails;
List<Email> emails;
string emailAddress;
using (Pop3Client client = new Pop3Client(Host, Port, Email, Password, false))
{
emailAddress = client.Email;
client.Connect();
totalEmails = client.GetEmailCount();
emails = client.FetchEmailList((totalEmails - ((page - 1) * 5)), NoOfEmailsPerPage);
}
int totalPages;
int mod = totalEmails % NoOfEmailsPerPage;
if (mod == 0)
totalPages = totalEmails / NoOfEmailsPerPage;
else
totalPages = ((totalEmails - mod) / NoOfEmailsPerPage) + 1;
for (int i = 0; i < emails.Count; i++)
{
AdminTransaction AT = new AdminTransaction();
DAL.Emails objEmail = new DAL.Emails();
Email email = emails[i];
int emailId = ((totalEmails - ((page - 1) * 5) - i));
TableCell noCell = new TableCell();
noCell.CssClass = "emails-table-cell";
noCell.Text = Convert.ToString(emailId);
objEmail.EmailNo = emailId;
TableCell fromCell = new TableCell();
fromCell.Text = email.From;
TableCell subjectCell = new TableCell();
subjectCell.Style["width"] = "300px";
subjectCell.Text = String.Format(DisplayEmailLink, emailId, page, email.Subject);
TableCell dateCell = new TableCell();
if (email.UtcDateTime != DateTime.MinValue)
dateCell.Text = email.UtcDateTime.ToString();
int x = AT.AddEmail(objEmail);
DataSet ds = AT.GetMailStatus(emailId);
if (ds.Tables[0].Rows.Count > 0)
{
// subjectCell.ForeColor = System.Drawing.Color.Red;
subjectCell.CssClass = "emails-table-cell";
fromCell.CssClass = "emails-table-cell";
dateCell.CssClass = "emails-table-cell";
}
else
{
subjectCell.CssClass = "emails-table-cellRead";
fromCell.CssClass = "emails-table-cellRead";
dateCell.CssClass = "emails-table-cellRead";
}
TableRow emailRow = new TableRow();
// emailRow.Cells.Add(noCell);
emailRow.Cells.Add(fromCell);
emailRow.Cells.Add(subjectCell);
emailRow.Cells.Add(dateCell);
//EmailsTable.Rows.Add(emailRow);
EmailsTable.Rows.AddAt(2 + i, emailRow);
}
if (totalPages > 1)
{
if (page > 1)
PreviousPageLiteral.Text = String.Format(SelfLink, page - 1, "Previous Page");
if (page > 0 && page < totalPages)
NextPageLiteral.Text = String.Format(SelfLink, page + 1, "Next Page");
}
EmailFromLiteral.Text = Convert.ToString(((page - 1) * NoOfEmailsPerPage) + 1);
EmailToLiteral.Text = Convert.ToString(page * NoOfEmailsPerPage);
EmailTotalLiteral.Text = Convert.ToString(totalEmails);
EmailLiteral.Text = emailAddress;
}
Related
I get "unfortunately app has stopped" error after phone restart. My Phone is Oreo 8 but another phone with Nougat 7.1.1 also having the same error after phone restart. I use James Montemagnos' MyStepCounter bound services codes from GitHub with some changes in VS 2017 (Xamarin Cross-Platform App). The app is working fine if once started after phone restart with this error, else it is not counting steps and not working on the background. If I check the app in Phone Settings-General-Battery-Power saving exclusions then it works with no problems after phone restart and it is counting steps on the background without starting the app on Oreo phone. But there are no settings for battery power saving exclusions on the other phone
BootReceiver.cs
[BroadcastReceiver(Enabled = true, Exported = true, DirectBootAware = true)]
[IntentFilter(new string[] { Intent.ActionBootCompleted, Intent.ActionLockedBootCompleted, "android.intent.action.QUICKBOOT_POWERON", "com.htc.intent.action.QUICKBOOT_POWERON" })]
public class BootReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
var stepServiceIntent = new Intent(context, typeof(StepService));
context.StartService(stepServiceIntent);
}
}
StepServiceBinder.cs
public class StepServiceBinder : Binder
{
StepService stepService;
public StepServiceBinder(StepService service)
{
this.stepService = service;
}
public StepService StepService
{
get { return stepService; }
}
}
StepServiceConnection.cs
public class StepServiceConnection : Java.Lang.Object, IServiceConnection
{
MainActivity activity;
public StepServiceConnection(MainActivity activity)
{
this.activity = activity;
}
public void OnServiceConnected(ComponentName name, IBinder service)
{
var serviceBinder = service as StepServiceBinder;
if (serviceBinder != null)
{
activity.Binder = serviceBinder;
activity.IsBound = true;
}
}
public void OnServiceDisconnected(ComponentName name)
{
activity.IsBound = false;
}
}
StepService.cs
public class StepServiceConnection : Java.Lang.Object, IServiceConnection
{
MainActivity activity;
public StepServiceConnection(MainActivity activity)
{
this.activity = activity;
}
public void OnServiceConnected(ComponentName name, IBinder service)
{
var serviceBinder = service as StepServiceBinder;
if (serviceBinder != null)
{
activity.Binder = serviceBinder;
activity.IsBound = true;
}
}
public void OnServiceDisconnected(ComponentName name)
{
activity.IsBound = false;
}
}
StepService.cs
[Service(Enabled = true)]
[IntentFilter(new String[] { "com.PedometerApp.StepService" })]
public class StepService : Service, ISensorEventListener, INotifyPropertyChanged
{
private SensorManager sManager;
private bool isRunning;
private long stepsToday = 0;
public bool WarningState
{
get;
set;
}
public long StepsToday
{
get { return stepsToday; }
set
{
if (stepsToday == value)
return;
stepsToday = value;
OnPropertyChanged("StepsToday");
Settings.CurrentDaySteps = value;
MessagingCenter.Send<object, long>(this, "Steps", Settings.CurrentDaySteps);
}
}
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
var alarmManager = ((AlarmManager)ApplicationContext.GetSystemService(AlarmService));
var intent2 = new Intent(this, typeof(StepService));
intent2.PutExtra("warning", WarningState);
var stepIntent = PendingIntent.GetService(ApplicationContext, 200, intent2, PendingIntentFlags.UpdateCurrent);
alarmManager.Set(AlarmType.Rtc, Java.Lang.JavaSystem
.CurrentTimeMillis() + 1000 * 60 * 60, stepIntent);
var warning = false;
if (intent != null)
warning = intent.GetBooleanExtra("warning", false);
Startup();
return StartCommandResult.Sticky;
}
public override void OnTaskRemoved(Intent rootIntent)
{
base.OnTaskRemoved(rootIntent);
UnregisterListeners();
var intent = new Intent(this, typeof(StepService));
intent.PutExtra("warning", WarningState);
((AlarmManager)GetSystemService(AlarmService)).Set(AlarmType.Rtc, Java.Lang.JavaSystem
.CurrentTimeMillis() + 500,
PendingIntent.GetService(this, 201, intent, 0));
}
private void Startup(bool warning = false)
{
CrunchDates(true);
if (!isRunning)
{
RegisterListeners();
WarningState = warning;
}
isRunning = true;
}
public override void OnDestroy()
{
base.OnDestroy();
UnregisterListeners();
isRunning = false;
CrunchDates();
}
void RegisterListeners()
{
sManager = GetSystemService(SensorService) as SensorManager;
sManager.RegisterListener(this, sManager.GetDefaultSensor(SensorType.StepCounter), SensorDelay.Ui);
}
void UnregisterListeners()
{
if (!isRunning)
return;
try
{
var sensorManager = (SensorManager)GetSystemService(Context.SensorService);
sensorManager.UnregisterListener(this);
isRunning = false;
}
catch (Exception ex)
{
}
}
StepServiceBinder binder;
public override Android.OS.IBinder OnBind(Android.Content.Intent intent)
{
binder = new StepServiceBinder(this);
return binder;
}
public void OnAccuracyChanged(Sensor sensor, SensorStatus accuracy)
{
//do nothing here
}
public void AddSteps(long count)
{
if (lastSteps == 0)
{
lastSteps = count;
}
newSteps = count - lastSteps;
if (newSteps < 0)
newSteps = 1;
else if (newSteps > 100)
newSteps = 1;
lastSteps = count;
CrunchDates();
Settings.TotalSteps += newSteps;
StepsToday = Settings.TotalSteps - Settings.StepsBeforeToday;
}
long newSteps = 0;
long lastSteps = 0;
public void OnSensorChanged(SensorEvent e)
{
if (lastSteps < 0)
lastSteps = 0;
var count = (long)e.Values[0];
WarningState = false;
AddSteps(count);
}
private void CrunchDates(bool startup = false)
{
if (!Utils.IsSameDay)
{
var yesterday = Settings.CurrentDay;
var dayEntry = StepEntryManager.GetStepEntry(yesterday);
if (dayEntry == null || dayEntry.Date.DayOfYear != yesterday.DayOfYear)
{
dayEntry = new StepEntry();
}
dayEntry.Date = yesterday;
dayEntry.Steps = Settings.CurrentDaySteps;
Settings.CurrentDay = DateTime.Today;
Settings.CurrentDaySteps = 0;
Settings.StepsBeforeToday = Settings.TotalSteps;
StepsToday = 0;
try
{
StepEntryManager.SaveStepEntry(dayEntry);
}
catch (Exception ex)
{
Console.WriteLine("Error {0}", ex.Message);
}
}
else if (startup)
{
StepsToday = Settings.TotalSteps - Settings.StepsBeforeToday;
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string name)
{
if (PropertyChanged == null)
return;
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
Dears,
I am implementing load more items to listview without a button.
My code:
public partial class DashBoardPage : ContentPage
{
ObservableCollection<string> Items;
bool isLoading;
public DashBoardPage()
{
InitializeComponent();
Items = new ObservableCollection<string>();
var listview = new ListView();
listview.ItemsSource = Items;
listview.ItemAppearing += (sender, e) =>
{
if (isLoading || Items.Count == 0)
return;
//hit bottom!
if (e.Item.ToString() == Items[Items.Count - 1])
{
LoadItems();
}
};
LoadItems();
}
public async void LoadItems()
{
isLoading = true;
HttpClient client = new HttpClient();
var response = await client.GetAsync("My Url");
string tweetJson = await response.Content.ReadAsStringAsync();
UserTweetResponse userTweetResponse = new UserTweetResponse();
if (tweetJson != "")
{
userTweetResponse = JsonConvert.DeserializeObject<UserTweetResponse>(tweetJson.ToString());
foreach (var tweet in userTweetResponse.userTweetsList)
{
Items.Add(tweet.ToString());
}
}
ListView1.ItemsSource = userTweetResponse.userTweetsList;
isLoading = false;
}
}
I refer the following link and confused with the for loop inside LoadItems():
https://montemagno.com/load-more-items-at-end-of-listview-in/
for (int i = 0; i < 20; i++)
{
Items.Add (string.Format("Item {0}", Items.Count));
}
In my case I am using itemSource property to bind the response to list view.
My model class:
public class UserTweetResponse
{
public List<UserTweetsList> userTweetsList { get; set; }
}
public class UserTweetsList
{
public int tweetId { get; set; }
public string tweetData { get; set; }
public string createdTime { get; set; }
public int commentCount { get; set; }
public int likeCount { get; set; }
public int flagCount { get; set; }
public string mediaUrl { get; set; }
public string tweetUser { get; set; }
public bool userLiked { get; set; }
public bool userFlagged { get; set; }
public bool isMediaUrlNull { get { return string.IsNullOrEmpty(mediaUrl); } }
}
How can I fix this?
Thanks in advance
You need to add your new tweets to your Items collection
public async void LoadItems()
{
isLoading = true;
HttpClient client = new HttpClient();
var response = await client.GetAsync("My Url");
string tweetJson = await response.Content.ReadAsStringAsync();
UserTweetResponse userTweetResponse = new UserTweetResponse();
if (tweetJson != "")
{
userTweetResponse = JsonConvert.DeserializeObject<UserTweetResponse>(tweetJson.ToString());
foreach (var tweet in userTweetResponse.userTweetsList)
{
Items.Add(tweet);
}
}
isLoading = false;
}
because the Observable collection is the ListView item source the new items will appear in the list.
Pasete this whole:
using System;
using System.Diagnostics;
using System.Net.Http;
using Newtonsoft.Json;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
namespace SmartTweet
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class DashBoardPage : ContentPage
{
int i = 1;
bool loadMore;
ObservableCollection<UserTweetsList> Items =new ObservableCollection<SmartTweet.UserTweetsList>();
bool isLoading;
UserTweetResponse userTweetResponse;
public DashBoardPage()
{
InitializeComponent();
ListView1.ItemAppearing += (sender, e) =>
{
if (isLoading || Items!=null && Items.Count == 0)
return;
//hit bottom
if (userTweetResponse.userTweetsList!=null && userTweetResponse.userTweetsList.Count>0)
{
UserTweetsList item = userTweetResponse.userTweetsList[userTweetResponse.userTweetsList.Count - 1];
if ((e.Item as UserTweetsList).tweetId.ToString() == item.tweetId.ToString())
{
Debug.WriteLine("Enter bottom");
loadMore = true;
UserTweetsList();
}
}
};
}
protected async override void OnAppearing()
{
await UserTweetsList();
base.OnAppearing();
}
async void ButtonClicked(Object sender, EventArgs e)
{
loadMore = true;
// await UserTweetsList();
}
public async Task UserTweetsList()
{
isLoading = true;
if (loadMore)
{
i = i + 1;
}
int countInInt = i * 3;
try
{
string applicationId = "1";
string siteId = "5";
string userId = "225";
string ownedBy = "me";
string period = "before";
string count = countInInt.ToString();
DateTime dt = DateTime.Now.ToLocalTime();
string date = dt.Year.ToString() + "-" + dt.Month.ToString() + "-" + dt.Day.ToString() + " " + dt.Hour.ToString() + ":" + dt.Minute.ToString() + ":" + dt.Second.ToString() + "." + dt.Millisecond.ToString();
HttpClient client = new HttpClient();
var response = await client.GetAsync("web service url");
string tweetJson = await response.Content.ReadAsStringAsync();
Debug.WriteLine("tweetList:>" + tweetJson);
userTweetResponse = new UserTweetResponse();
if (tweetJson != "")
{
userTweetResponse = JsonConvert.DeserializeObject<UserTweetResponse>(tweetJson.ToString());
foreach (var tweet in userTweetResponse.userTweetsList)
{
if (!Items.Contains(tweet))
{
Items.Add(tweet);
}
//Items.Add(tweet.ToString());
}
}
ListView1.ItemsSource = userTweetResponse.userTweetsList;
isLoading = false;
if (userTweetResponse.userTweetsList.Count == 0)
{
//loadMoreButton.IsVisible = false;
blue_holo_circle.IsVisible = false;
blueLine.IsVisible = false;
}
else
{
//loadMoreButton.IsVisible = true;
blue_holo_circle.IsVisible = true;
blueLine.IsVisible = true;
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("Exception:>" + ex);
}
}
}
}
I have a static class that needs to pass a generic List of strings to a function using an integer as a index to the List in the class. The problem is the static class doesn't have a List collect and I don't have a proper index to access the class in the function it is passed to. The class, the calling code, and the receiving function are below.
My Class:
public class QueryContainer
{
public static QueryContainer Instance = new QueryContainer();
private int _id;
private string _query = "";
private int _searchID;
public QueryContainer() { }
public string Query
{
get
{
if (Instance != null)
return Instance._query;
else
return "";
}
set { _query = value; _id =+ 1; }
}
public int ID { get { return _id; } }
public int SearchID
{
set { _searchID = value; }
get { return _searchID; }
}
}
The calling code:
public int GetAccountSortByAccountCode(int account)
{
int Id = 0;
QueryContainer.Instance.Query = "SELECT ac_sort_order FROM lkup_account_codes where ac_code = " + account.ToString();
return Convert.ToInt32(ExecuteScaler(Id));
}
The function that the static class is passed to:
public int GetAccountSortByAccountCode(int account)
{
int Id = 0;
QueryContainer.Instance.Query = "SELECT ac_sort_order FROM lkup_account_codes where ac_code = " + account.ToString();
return Convert.ToInt32(ExecuteScaler(Id));
}
The Function
protected Object ExecuteScaler(int ID)
{
object returnValue = null;
if (!_iserror)
{
if (_trace)
{ DoTrace("TAMIS.Data.Loader.ExecuteScalar", QueryContainer.Instance.Query); }
if (_connection == null || _connection.State == ConnectionState.Closed)
{
OpenConnection();
}
DbCommand command = _provider.CreateCommand();
command.Connection = _connection;
{
command.CommandText = QueryContainer.Instance.Query;
command.CommandType = CommandType.Text;
if (_useTransaction) { command.Transaction = _transaction; }
try
{
returnValue = command.ExecuteScalar();
}
catch (Exception ex)
{
if (ex is EntryPointNotFoundException)
throw ex;
//if (_useTransaction == true)
//_transaction.Rollback();
RollBack();
LogBLL bll = new LogBLL();
bll.WriteErrorLog(ex);
_iserror = true;
}
finally
{
if ((!KeepAlive && _connection.State == ConnectionState.Open) || _iserror == true)
{
CloseConnection();
}
}
}
}
else
{
returnValue = -1;
}
return returnValue;
}
You are using QueryContainer as a Singleton.
In ASP.Net, you receives multiple requests from different users. It is not a good way to construct dynamic query.
Basically, what you are doing is all requests will use same QueryContainer instance. I don't think it is what you want.
The bottom line is do not use static in your scenario.
I've recently been re-factoring my code to move from inproc to Session State. I've created a new class that I built from the start to be serializable. I'm currently getting the 'Unable to serialize the session state.' error. However, I am able to serialize the class using JsonConvert (newtonsoft).
Are methods not allowed or something?
This is what it looks like:
[Serializable()]
public class SessionStateObject
{
public int CurrentSessionId { get; set; }
public int CurrentAssessmentId { get; set; }
public int CurrentAssessmentElementId { get; set; }
public int CurrentUserId { get; set; }
public Dictionary<string, int> AssessmentItemsIds { get; set; }
public Dictionary<string, int> SessionResponseIds { get; set; }
public List<string> AdministeredItemOrderByName;
public string LastVisitedItem;
public int? TotalAssessmentCurrentItemOrder;
public RenderablePersistanceObject RenderablePersistance;
#region formula engine section variables
public string BranchingResult { get; set; }
public string ContentOutput { get; set; }
public int CurrentItemId { get; set; }
public int VirtualWorkingItemId { get; set; }
public bool isCloneItem { get; set; }
public bool wasPreFormulaRun;
public bool wasContentOutput;
public bool wasPrefillReached;
public bool isVirtual;
public List<string> FormulaStack { get; set; }
public List<string> ItemNameTokens { get; set; }
public string serializedJSContext { get; set; }
public string CloneSourceItem { get; set; }
public int itemsAbletoFastForwardThrough { get; set; }
#endregion
private Dictionary<int, int> itemIdByMultiGroupId; //key is itemId, val is groupId
private Dictionary<int, List<int>> MultiGroupIdByItemIds; //key is groupId, val is itemId
public SessionStateObject()
{
RenderablePersistance = new RenderablePersistanceObject();
AssessmentItemsIds = new Dictionary<string, int>();
SessionResponseIds = new Dictionary<string, int>();
AdministeredItemOrderByName = new List<string>();
FormulaStack = new List<string>();
ItemNameTokens = new List<string>();
itemIdByMultiGroupId = new Dictionary<int, int>();
MultiGroupIdByItemIds = new Dictionary<int, List<int>>();
}
public void initMultiItemGroups(Assessment assessment, NetScidDbContainer dbContext)
{
List<MultiItem> assessmentMultiItems = (from multi in dbContext.MultiItems
where multi.AssessmentId == assessment.Id
select multi).ToList();
List<int> uniqueGroupIds = new List<int>();
foreach (MultiItem mItem in assessmentMultiItems)
{
itemIdByMultiGroupId.Add(mItem.ItemId, mItem.GroupId);
if (!uniqueGroupIds.Contains(mItem.GroupId))
{
uniqueGroupIds.Add(mItem.GroupId);
}
}
foreach (int groupId in uniqueGroupIds)
{
List<int> ItemIds = (from itemGroup in assessmentMultiItems
where itemGroup.GroupId == groupId
orderby itemGroup.Id ascending
select itemGroup.ItemId).ToList();
MultiGroupIdByItemIds.Add(groupId, ItemIds);
}
}
public List<int> GetItemIdsFromSingleItemId(int itemId)
{
List<int> foundItemIDs = new List<int>();
int foundGroupId = -1;
if (this.itemIdByMultiGroupId.ContainsKey(itemId))
{
foundGroupId = this.itemIdByMultiGroupId[itemId];
}
if (this.MultiGroupIdByItemIds.ContainsKey(foundGroupId))
{
foundItemIDs = this.MultiGroupIdByItemIds[foundGroupId];
}
return foundItemIDs;
}
public void nullifyRenderable()
{
this.RenderablePersistance = null;
}
public void PersistRenderable(IRenderable renderable)
{
this.RenderablePersistance = new RenderablePersistanceObject();
if (renderable is MultiItemRenderable)
{
//get list of item IDs from the multi-item lookup
this.RenderablePersistance.isMultiItem = true;
this.RenderablePersistance.primaryItemId = ((Item)((MultiItemRenderable)renderable).IndexedItems.Last()).Id;
}
else //regular renderable
{
this.RenderablePersistance.isMultiItem = false;
this.RenderablePersistance.primaryItemId = ((Item)renderable).Id;
}
}
public AssessmentRuntime StartAdministrativeSession(NetScidDbContainer dataContext, Assessment assessment, User currentUser, string pid = "1")
{
AssessmentRuntime newRuntime = new AssessmentRuntime(this, dataContext);
Session newSession = new Session();
assessment.PrepElements();
PermissionEntity rootPE = new PermissionEntity();
if (currentUser != null)
{
rootPE = PermissionEntityHelper.GetRootPermissionEnity(dataContext, currentUser);
}
else
{
rootPE = (from adminpe in dataContext.PermissionEntities
where adminpe.Name == "TelesageAdmin"
select adminpe
).FirstOrDefault();
}
newSession.Participant = (from pids in dataContext.ParticipantIdAliasLookups
where pid == pids.AliasId && pids.RootPermissionEntity.Id == rootPE.Id
select pids.Participant).FirstOrDefault();
if (newSession.Participant == null)
{
Participant newParticipant = new Participant();
ParticipantIdAliasLookup newPidAlias = new ParticipantIdAliasLookup();
newParticipant.ParticipantDataJSON = "";
newPidAlias.AliasId = pid;
newPidAlias.RootPermissionEntity = rootPE;
newParticipant.AliasLookup = newPidAlias;
newParticipant.PermissionEntities.Add(currentUser.PermissionEntity);
newParticipant.PermissionEntities.Add(rootPE);
newSession.Participant = newParticipant;
dataContext.Participants.AddObject(newParticipant);
dataContext.ParticipantIdAliasLookups.AddObject(newPidAlias);
}
newSession.Assessment = assessment;
newSession.User = currentUser;
newSession.StartTime = DateTime.Now;
newSession.PermissionEntity = currentUser.PermissionEntity;
newSession.SetSessionData("engineversion", typeof(SmartQWeb.MvcApplication).Assembly.GetName().Version.ToString());
newSession.SetSessionData("assessmentname", newSession.Assessment.Name);
newSession.SetSessionData("assessmentversion", newSession.Assessment.Version);
newSession.SetSessionData("computername", Environment.MachineName);
newSession.SetSessionData("username", currentUser.Name);
dataContext.Sessions.AddObject(newSession);
newSession.SetSessionData("dxdata", JsonConvert.SerializeObject(newRuntime.RenderedDiagnoses));
newRuntime.formulaEngine = new FixedLengthFormulaEngine(newRuntime);
SessionLog newSessionLog = new SessionLog();
dataContext.SessionLogs.AddObject(newSessionLog);
newSession.SessionLog = newSessionLog;
dataContext.SaveChanges();
initMultiItemGroups(assessment, dataContext);
this.CurrentSessionId = newSession.Id;
this.CurrentUserId = currentUser.Id;
this.CurrentAssessmentId = assessment.Id;
newRuntime.Context = new RuntimeContext(this, dataContext);
this.GetAssessmentItems(assessment); //to populate the items dict
newRuntime.formulaEngine.InitializeContext(this.AssessmentItemsIds.Keys.ToList());
newRuntime.RenderedDiagnoses = new RenderedDiagnosisModel(newRuntime.Context.AdministeredItemOrderByName);
newRuntime.Context.Logger.WriteLog("Session started with assessment: " + newRuntime.Context.Assessment.Name + " with version: " + newRuntime.Context.Assessment.Version);
newRuntime.Context.Logger.WriteLog("Session started by user: " + newRuntime.Context.CurrentUser.Name + "for participant ID: " + newSession.ParticipantId);
return newRuntime;
}
//start from a previous existing session
public AssessmentRuntime StartAdministrativeSession(NetScidDbContainer dataContext, Assessment assessment, Session previousSession, User currentUser, string pid = "", string resumefromlatest = "false")
{
AssessmentRuntime newRuntime = new AssessmentRuntime(this, dataContext);
Session newSession = new Session();
Assessment sessionAssessment = assessment;
newSession.ParticipantId = previousSession.ParticipantId;
//THE OTHER ENTITIES BESIDES THE SESSION NEED TO BE DETATCHED AND RE-ATTACHED (BY BEING ADDED TO THE NEW SESSION)
assessment.PrepElements();
newRuntime.RenderedDiagnoses = new RenderedDiagnosisModel(newRuntime.Context.AdministeredItemOrderByName);
List<Response> prevresponses = previousSession.Responses.ToList();
if (sessionAssessment == assessment)
{
foreach (Response prevresponse in prevresponses)
{
newRuntime.Context.CachedAssessmentResponses.Add(prevresponse.Item.ItemName, prevresponse);
dataContext.Detach(prevresponse);
newSession.Responses.Add(prevresponse);
}
}
else
{
//the sessionAssessment is now the more up-to-date one so the responses pulled will have to be mapped, not just detatched and copied
foreach (Response prevresponse in prevresponses)
{
Dictionary<string, FixedLengthItem> newAssessmentItemNames = AssessmentHelper.GetAssessmentItems(sessionAssessment);
if (!newAssessmentItemNames.ContainsKey(prevresponse.Item.ItemName))
continue;
Response newResponse = new Response
{
NumericValue = prevresponse.NumericValue,
Item = newAssessmentItemNames[prevresponse.Item.ItemName],
ItemName = prevresponse.Item.ItemName,
AdministeredOrder = -1,
Value = prevresponse.Value
};
newRuntime.Context.CachedAssessmentResponses.Add(newResponse.Item.ItemName, newResponse);
newSession.Responses.Add(newResponse);
}
}
newSession.SessionDataJSON = previousSession.SessionDataJSON;
//DxData
newRuntime.RenderedDiagnoses =
JsonConvert.DeserializeObject<RenderedDiagnosisModel>(newSession.GetSessionData("dxdata"));
//inc session is =2 when the the session has been resumed by
previousSession.IncSession = 2;
newSession.SetSessionData("previoussession", previousSession.Id.ToString());
newSession.Participant = previousSession.Participant;
newSession.Assessment = sessionAssessment;
newSession.User = currentUser;
newSession.PermissionEntity = currentUser.PermissionEntity;
newSession.StartTime = DateTime.Now;
dataContext.Sessions.AddObject(newSession);
dataContext.SaveChanges();
newRuntime.formulaEngine = new FixedLengthFormulaEngine(newRuntime);
initMultiItemGroups(assessment, dataContext);
newSession.SetSessionData("continuedsession", newSession.Id.ToString());
this.CurrentSessionId = newSession.Id;
this.CurrentUserId = currentUser.Id;
this.CurrentAssessmentId = assessment.Id;
this.GetAssessmentItems(assessment); //to populate the items dict
this.SetUpPreviousResponses(newSession); //populates SSO responses
newRuntime.Context = new RuntimeContext(this, dataContext);
if (newRuntime.RenderedDiagnoses != null)
newRuntime.RenderedDiagnoses.reInitAdminOrder(newRuntime.Context.AdministeredItemOrderByName);
newRuntime.formulaEngine.InitializeContext(this.AssessmentItemsIds.Keys.ToList());
return newRuntime;
}
//start from the SSO
public AssessmentRuntime ResumeSessionFromState(NetScidDbContainer dataContext)
{
AssessmentRuntime newRuntime = new AssessmentRuntime(this, dataContext);
newRuntime.formulaEngine = new FixedLengthFormulaEngine(newRuntime);
newRuntime.formulaEngine.InitializeSerializedContext(serializedJSContext);
newRuntime.Context = new RuntimeContext(this, dataContext);
if (this.CurrentAssessmentElementId != 0)
{
newRuntime.CurrentAssessmentElement = (from ae in dataContext.AssessmentElements
where ae.Id == this.CurrentAssessmentElementId
select ae).FirstOrDefault();
newRuntime.CurrentAssessmentElement.GetNewRuntime(newRuntime.Context);
}
return newRuntime;
}
private void GetAssessmentItems(Assessment assessment)
{
var fixedLengthElements = (from elements in assessment.AssessmentElements
where elements is FixedLengthBlock
select elements);
foreach (FixedLengthBlock elemblock in fixedLengthElements)
{
foreach (FixedLengthItem item in elemblock.ItemBank.Items)
{
item.aeRef = elemblock;
AssessmentItemsIds.Add(item.ItemName, item.Id);
}
}
}
private void SetUpPreviousResponses(Session newSession)
{
//put response IDs by itemname into this dictionary
SessionResponseIds = (from response in newSession.Responses
select response).ToDictionary(key => key.ItemName, value => value.Id);
}
}
And the RenderablePersistanceObject looks like this:
public class RenderablePersistanceObject
{
public int primaryItemId;
public int MultiItemGroupId;
public bool isMultiItem;
}
You can't serialize a straight Dictionary like that. You can take a look at this MSDN article for suggestions on implementing. If you don't truly need a Dictionary, perhaps List> might work better?
As Erik pointed out, it was the lack of the adorner [Serializable()] on that other object that caused the problem. Adding it solved my issue.
With .net 4.0/Preview kit 2, we can generate help pages for WCF REST.
Is there anyway we can do the same for MVC ?
www.somewebsite.com/search/help
I can create help pages (views) and expose them.
I can generate XSD schema and spit out as xml.
Any other guidance/suggestions ?
I want to generate something similar to this.
UriTemplate http://somewebsite.com/Search/
Method PUT
Response Format Xml
Response Schema http://somewebsite.com/help/response/schema
Response Example http://somewebsite.com/help/response/example
Update:
I was able to create documentation by using below code.
Route : somewebsite.com/Media/
HelpRoute : somewebsite.com/Media/Help (Append help to the parent route)
Add routes accordingly. See below example.
routes.MapRoute("Search",
"Search/Quick/",
new { controller = "Search", action = "Search" },
new { httpMethod = new HttpMethodConstraint("PUT") }
);
routes.MapRoute("SearchHelp",
"Search/Quick/Help",
new { controller = "Search", action = "Search" },
new { helpConstraint = new HelpConstraint { Help = true, SampleType = typeof(Search) } }
);
public class HelpResult : ViewResult
{
private string HelpPage { get; set; }
private string folderName = "HelpFiles";
private HttpServerUtilityBase server { get; set; }
private Type sampleType { get; set; }
private string schemaName { get; set; }
const string htmlFormat =
#"
<html>
<head>
<title>Help</title>
</head>
<body>
<li>URL - {0}</li>
<li>Verb - {1}</li>
{2}
</body>
</html>
";
public override void ExecuteResult(ControllerContext context)
{
server = context.HttpContext.Server;
StringBuilder parentUrl = new StringBuilder();
var data = context.RouteData.Route.GetRouteData(context.HttpContext);
//Getting requested route url.
string url = ((Route)(data.Route)).Url;
//Getting parent route from requested route url by removing "Help" from the route.
string newUrl = url.Substring(0, url.Length - 4);
parentUrl.Append("/" + newUrl);
sampleType = data.GetSampleType();
var validVerbs = GetValidVerbs(MakeAppRelative(parentUrl.ToString()));
CreateSchema(sampleType, true);
HelpPage = string.Format(htmlFormat, newUrl, validVerbs, CreateInputSampleText());
context.HttpContext.Response.Output.Write(HelpPage);
}
private string CreateInputSampleText()
{
if (sampleType != null && !string.IsNullOrEmpty(sampleType.Name))
{
string sampleText =
#"<li>Input Sample Xml - <a href='\HelpFiles\{0}.xml'>Click Here</a></li>
<li>Input Sample Json - <a href='\HelpFiles\{0}.txt'>Click Here</a></li>
<li>Input Schema - <a href='\HelpFiles\{1}'>Click Here</a></li>";
sampleText = string.Format(sampleText, sampleType.Name, schemaName);
return sampleText;
}
return string.Empty;
}
private static string MakeAppRelative(string url)
{
if (!url.StartsWith("~"))
{
if (!url.StartsWith("/"))
url = "~/" + url;
else
url = "~" + url;
}
return url;
}
private static string GetValidVerbs(string Url)
{
StringBuilder validVerbs = new StringBuilder();
var httpMethodOptions = new[] { "GET", "POST", "PUT", "DELETE", "HEAD" };
foreach (var httpMethodOption in httpMethodOptions)
{
var fakeContext = new FakeHttpContext(MakeAppRelative(Url), httpMethodOption);
foreach (Route route in RouteTable.Routes)
{
var rd = route.GetRouteData(fakeContext);
if (rd != null)
{
bool errorControllerApplied = route.IsErrorController();
if (!errorControllerApplied)
{
validVerbs.Append(httpMethodOption);
}
}
}
}
return validVerbs.ToString();
}
private void CreateFile(Type type, Stream stream)
{
using (Stream inputStream = stream)
{
schemaName = sampleType + "Schema.xml";
string folder = Path.GetFullPath(Path.Combine(server.MapPath("~"), folderName));
string file = Path.Combine(folder, schemaName);
if (!Directory.Exists(folder))
Directory.CreateDirectory(folder);
using (FileStream fileStream = new FileStream(file, FileMode.Create))
{
byte[] fileContent = new byte[inputStream.Length];
inputStream.Read(fileContent, 0, fileContent.Length);
fileStream.Write(fileContent, 0, fileContent.Length);
fileStream.Flush();
}
}
}
private void CreateSchema(Type type, bool isXmlSerializerType)
{
System.Collections.IEnumerable schemas;
if (isXmlSerializerType)
{
XmlReflectionImporter importer = new XmlReflectionImporter();
XmlTypeMapping typeMapping = importer.ImportTypeMapping(type);
XmlSchemas s = new XmlSchemas();
XmlSchemaExporter exporter = new XmlSchemaExporter(s);
exporter.ExportTypeMapping(typeMapping);
schemas = s.GetSchemas(null);
}
else
{
XsdDataContractExporter exporter = new XsdDataContractExporter();
exporter.Export(type);
schemas = exporter.Schemas.Schemas();
}
using (MemoryStream stream = new MemoryStream())
{
XmlWriterSettings xws = new XmlWriterSettings() { Indent = true };
using (XmlWriter w = XmlWriter.Create(stream, xws))
{
w.WriteStartElement("Schemas");
foreach (XmlSchema schema in schemas)
{
if (schema.TargetNamespace != "http://www.w3.org/2001/XMLSchema")
{
schema.Write(w);
}
}
}
stream.Seek(0, SeekOrigin.Begin);
CreateFile(type, stream);
}
}
public static class RouteDataExtensions
{
public static bool IsHelpConstraintApplied(this RouteData data)
{
if (data != null && data.Route != null)
{
var constraints = ((Route) (data.Route)).Constraints;
var helpConstraint = (from c in constraints.Values
where c.GetType().Equals(typeof (HelpConstraint))
select c).FirstOrDefault();
if (helpConstraint != null)
{
return true;
}
}
return false;
}
public static Type GetSampleType(this RouteData data)
{
if (data != null && data.Route != null)
{
var constraints = ((Route)(data.Route)).Constraints;
var helpConstraint = (from c in constraints.Values
where c.GetType().Equals(typeof(HelpConstraint))
select c).FirstOrDefault();
if (helpConstraint != null)
{
return ((HelpConstraint) helpConstraint).SampleType;
}
}
return null;
}
public static string GetMethodType(this RouteData data)
{
if (data != null && data.Route != null)
{
var constraints = ((Route) (data.Route)).Constraints;
var httpMethodConstraint = (from c in constraints.Values
where c.GetType().Equals(typeof (HttpMethodConstraint))
select c).FirstOrDefault();
if (httpMethodConstraint != null)
{
return ((HttpMethodConstraint) httpMethodConstraint).AllowedMethods.Single();
}
}
return null;
}
public static bool IsErrorController(this Route data)
{
if (data != null)
{
var defaults = ((Route)(data)).Defaults;
var controllerName = (from c in defaults.Values
where c.ToString().Contains("Error")
select c).FirstOrDefault();
if (controllerName != null)
{
return true;
}
}
return false;
}
public static RouteData GetRouteDataByUrl(this string url)
{
string httpMethod = "PUT";
var fakeContext = new FakeHttpContext(MakeAppRelative(url), httpMethod);
return RouteTable.Routes.GetRouteData(fakeContext);
}
private static string MakeAppRelative(string url)
{
if (!url.StartsWith("~"))
{
if (!url.StartsWith("/"))
url = "~/" + url;
else
url = "~" + url;
}
return url;
}
}
public class HelpConstraint : IRouteConstraint
{
public bool Help { get; set; }
public Type SampleType { get; set; }
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
if(Help)
{
return true;
}
return false;
}
}
References
http://stephenwalther.com/blog/archive/2008/08/03/asp-net-mvc-tip-29-build-a-controller-to-debug-your-custom-routes.aspx
http://aspnet.codeplex.com/releases/view/24644
This code is not bug free. Please post improvements if you have any. Use it at your own risk.
Not exactly sure what you are looking for, but you can check out GhostDoc:
http://submain.com/products/ghostdoc.aspx
I use this to generate XML documentation in MVC.
Most probably you have solved your issue by now. Anyway, I think you need IApiExplorer. Have a look at this blog.