asp.net membership api - login control (where is the code executing?) - asp.net

here is the login page that created for you when you create a default application in asp.net and i am trying to understand where does the actually code validating/authenticating the userid and password?, i did not find any code-behind code except this: where does it validating the username and password?
i see the CommandName="Login" but dont find the code....
protected void Page_Load(object sender, EventArgs e)
{
RegisterHyperLink.NavigateUrl = "Register.aspx?ReturnUrl=" + HttpUtility.UrlEncode(Request.QueryString["ReturnUrl"]);
}
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
<h2>
Log In
</h2>
<p>
Please enter your username and password.
<asp:HyperLink ID="RegisterHyperLink" runat="server" EnableViewState="false">Register</asp:HyperLink> if you don't have an account.
</p>
<asp:Login ID="LoginUser" runat="server" EnableViewState="false" RenderOuterTable="false">
<LayoutTemplate>
<span class="failureNotification">
<asp:Literal ID="FailureText" runat="server"></asp:Literal>
</span>
<asp:ValidationSummary ID="LoginUserValidationSummary" runat="server" CssClass="failureNotification"
ValidationGroup="LoginUserValidationGroup"/>
<div class="accountInfo">
<fieldset class="login">
<legend>Account Information</legend>
<p>
<asp:Label ID="UserNameLabel" runat="server" AssociatedControlID="UserName">Username:</asp:Label>
<asp:TextBox ID="UserName" runat="server" CssClass="textEntry"></asp:TextBox>
<asp:RequiredFieldValidator ID="UserNameRequired" runat="server" ControlToValidate="UserName"
CssClass="failureNotification" ErrorMessage="User Name is required." ToolTip="User Name is required."
ValidationGroup="LoginUserValidationGroup">*</asp:RequiredFieldValidator>
</p>
<p>
<asp:Label ID="PasswordLabel" runat="server" AssociatedControlID="Password">Password:</asp:Label>
<asp:TextBox ID="Password" runat="server" CssClass="passwordEntry" TextMode="Password"></asp:TextBox>
<asp:RequiredFieldValidator ID="PasswordRequired" runat="server" ControlToValidate="Password"
CssClass="failureNotification" ErrorMessage="Password is required." ToolTip="Password is required."
ValidationGroup="LoginUserValidationGroup">*</asp:RequiredFieldValidator>
</p>
<p>
<asp:CheckBox ID="RememberMe" runat="server"/>
<asp:Label ID="RememberMeLabel" runat="server" AssociatedControlID="RememberMe" CssClass="inline">Keep me logged in</asp:Label>
</p>
</fieldset>
<p class="submitButton">
<asp:Button ID="LoginButton" runat="server" CommandName="Login" Text="Log In" ValidationGroup="LoginUserValidationGroup"/>
</p>
</div>
</LayoutTemplate>
</asp:Login>
</asp:Content>

The implement is in the Login.OnBubbleEvent method. For more information, refer to http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.login.onbubbleevent.aspx

Login.OnBubbleEvent as Edward Zhu pointed out is the correct answer. To further the understanding what happens here is the code snippet from System.Web.dll for the event (using Reflector.exe)
protected override bool OnBubbleEvent(object source, EventArgs e)
{
bool flag = false;
if (e is CommandEventArgs)
{
CommandEventArgs args = (CommandEventArgs) e;
if (string.Equals(args.CommandName, LoginButtonCommandName, StringComparison.OrdinalIgnoreCase))
{
this.AttemptLogin();
flag = true;
}
}
return flag;
}
LoginButtonCommandName defaults to "Login"
Pawel

Search in your code for a class that inherits : MembershipProvider
I have this class
public class TsMembershiProvider : MembershipProvider
{
private Dictionary<string, MembershipUser> _Users;
// MembershipProvider Properties
public override string ApplicationName
{
get { throw new NotSupportedException(); }
set { throw new NotSupportedException(); }
}
public override bool EnablePasswordRetrieval
{
get { return true; }
}
public override bool EnablePasswordReset
{
get { return true; }
}
public override int MaxInvalidPasswordAttempts
{
get { throw new NotSupportedException(); }
}
public override int MinRequiredNonAlphanumericCharacters
{
get { return 2; }
}
public override int MinRequiredPasswordLength
{
get { return 5; }
}
public override int PasswordAttemptWindow
{
get { throw new NotSupportedException(); }
}
public override MembershipPasswordFormat PasswordFormat
{
get { throw new NotSupportedException(); }
}
public override string PasswordStrengthRegularExpression
{
get { throw new NotSupportedException(); }
}
public override bool RequiresQuestionAndAnswer
{
get { return false; }
}
public override bool RequiresUniqueEmail
{
get { throw new NotSupportedException(); }
}
// MembershipProvider Methods
public override void Initialize(string name, NameValueCollection config)
{
// Verify that config isn't null
if (config == null)
throw new ArgumentNullException("config");
// Assign the provider a default name if it doesn't have one
if (String.IsNullOrEmpty(name))
name = "TsMembershipProvider";
// Add a default "description" attribute to config if the
// attribute doesn't exist or is empty
if (string.IsNullOrEmpty(config["description"]))
{
config.Add("description", "Membership provider");
}
// Call the base class's Initialize method
base.Initialize(name, config);
// Throw an exception if unrecognized attributes remain
if (config.Count > 0)
{
string attr = config.GetKey(0);
if (!String.IsNullOrEmpty(attr))
throw new ProviderException
("Unrecognized attribute: " + attr);
}
}
public override bool ValidateUser(string username, string password)
{
if (String.IsNullOrEmpty(username) || String.IsNullOrEmpty(password))
return false;
SqlDataReader dr = SqlHelper.ExecuteReader(SqlHelper.ConnString, "spc_UserAuthorization", username, password);
bool ret = dr.HasRows;
return ret;
}
public override MembershipUser GetUser(string username, bool userIsOnline)
{
// Note: This implementation ignores userIsOnline
// Validate input parameters
if (String.IsNullOrEmpty(username))
return null;
// Retrieve the user from the database
MembershipUser user = MU(username, userIsOnline); //userIsOnline = AltEmail - gets alternative email (hvb)
return user;
}
public override MembershipUserCollection GetAllUsers(int pageIndex,
int pageSize, out int totalRecords)
{
// Note: This implementation ignores pageIndex and pageSize,
// and it doesn't sort the MembershipUser objects returned
// Make sure the data source has been loaded
ReadMembershipDataStore();
MembershipUserCollection users =
new MembershipUserCollection();
foreach (KeyValuePair<string, MembershipUser> pair in _Users)
users.Add(pair.Value);
totalRecords = users.Count;
return users;
}
public override int GetNumberOfUsersOnline()
{
throw new NotSupportedException();
}
public override bool ChangePassword(string username, string oldPassword, string newPassword)
{
MembershipUser u = Membership.GetUser(username);
if (u == null || oldPassword != u.GetPassword())
{
return false;
}
if (newPassword.Length < MinRequiredPasswordLength)
{
return false;
}
CharEnumerator chars = newPassword.GetEnumerator();
int nr = 0;
while (chars.MoveNext())
{
if (!Char.IsLetterOrDigit(chars.Current))
nr++;
}
if (MinRequiredNonAlphanumericCharacters < nr)
{
return false;
}
// CALL TO SQL TO CHANGE PASSWORD
return true;
}
public override bool
ChangePasswordQuestionAndAnswer(string username,
string password, string newPasswordQuestion,
string newPasswordAnswer)
{
throw new NotSupportedException();
}
public override MembershipUser CreateUser(string username,
string password, string email, string passwordQuestion,
string passwordAnswer, bool isApproved, object providerUserKey,
out MembershipCreateStatus status)
{
//SOME CODE i DON'T WHANT YOU TO SEE :)
string strStatus = "";
string strUserid = "";
status = (MembershipCreateStatus)Enum.Parse(typeof(MembershipCreateStatus), strStatus, true);
if (status == MembershipCreateStatus.Success)
{
int userid = 0;
try
{
userid = Convert.ToInt32(strUserid);
}
catch
{
status = MembershipCreateStatus.ProviderError;
}
MembershipUser mu = MU(username);
return mu;
}
else
{
return null;
}
}
public override bool DeleteUser(string username,
bool deleteAllRelatedData)
{
throw new NotSupportedException();
}
public override MembershipUserCollection
FindUsersByEmail(string emailToMatch, int pageIndex,
int pageSize, out int totalRecords)
{
throw new NotSupportedException();
}
public override MembershipUserCollection
FindUsersByName(string usernameToMatch, int pageIndex,
int pageSize, out int totalRecords)
{
throw new NotSupportedException();
}
public override string GetPassword(string username, string answer)
{
//GET PASS FROM SQL
return "";
}
public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
{
string UserName = (string)SqlHelper.ExecuteScalar(SqlHelper.ConnString, CommandType.Text, "select .... WHERE UserID = " + providerUserKey.ToString());
MembershipUser m = MU(UserName, userIsOnline);
return m;
}
public override string ResetPassword(string username,
string answer)
{
throw new NotSupportedException();
}
public override bool UnlockUser(string userName)
{
throw new NotSupportedException();
}
public override void UpdateUser(MembershipUser user)
{
throw new NotSupportedException();
}
// Helper method
private void ReadMembershipDataStore()
{
lock (this)
{
}
}
private MembershipUser MU(string UserName)
{
return MU(UserName, false);
}
private MembershipUser MU(string UserName, bool isOnline)
{
MembershipUser user = null;
//SOME CODE
return user;
}
}

Have you looked in the code behind file? This would be like login.aspx.cs.

Related

ASP.NET GridView can`t find properties

I have an ObjectDataSource, bind to static class state with all methods: select, update, insert, delete to work with instances of serviceRecord class. It looks fine. But when I bind it with GridView, GridView can`t find any serviceRecord property and auto generate columns. Without auto generation i have an exception: HttpException (0x80004005): A field or property with the name 'serviceStart' was not found on the selected data source.
<div style="text-align: center">
<asp:ObjectDataSource ID="ServiceRecordsDataSource" runat="server"
DataObjectTypeName="LaretsState.serviceRecord" TypeName="LaretsState.state"
DeleteMethod="deleteRecord" InsertMethod="addRecord"
SelectMethod="getRecords" UpdateMethod="updateRecord" >
</asp:ObjectDataSource>
<asp:GridView ID="GridView" runat="server" AutoGenerateColumns="False"
ObjectDataSourceId ="ServiceRecordsDataSource" DataSourceID="ServiceRecordsDataSource">
<Columns>
<asp:BoundField DataField="serviceStart" DataFormatString="dd:MM:yyyy hh:mm" HeaderText="Date and time of service" />
<asp:BoundField DataField="serviceDuration" DataFormatString="mm" HeaderText="Duration" />
<asp:BoundField DataField="creationTime" DataFormatString="dd.MM.yyyy hh.mm" HeaderText="Creation time" />
</Columns>
</asp:GridView>
The classes are:
namespace LaretsState
{
public static class state
{
public static actualState actualState
{ get { return new actualState(getActualState(), getNextRecord()); } }
private static List<serviceRecord> _plan = new List<serviceRecord>();
static state() { }
public static List<serviceRecord> getRecords()
{
return _plan;
}
public static void updateRecord(serviceRecord record)
{
serviceRecord newRecord = record;
lock (_plan)
{
serviceRecord oldRecord = _plan.Where(r=> r.id== record.id).FirstOrDefault();
if (oldRecord == null)
{ throw new ArgumentException("В плане отсутствует запись с id " + record.id, "recordid"); }
var ColissionRecords = GetCollisionRecords(newRecord);
if (ColissionRecords.Count() > 1 ||
ColissionRecords.Count() == 1 && !ColissionRecords.Contains(oldRecord))
{ throw new Exception("На предложенное время уже запланировано обслуживание"); }
oldRecord = newRecord;
//_plan.Remove(oldRecord);
//_plan.Add(newRecord);
}
}
public static void deleteRecord(serviceRecord record)
{
_plan.Remove(record);
}
public static void addRecord(serviceRecord record)
{
lock (_plan)
{
var ColissionRecords = GetCollisionRecords(record);
if (ColissionRecords.Count() > 1 )
{ throw new Exception("На предложенное время уже запланировано обслуживание"); }
_plan.Add(record);
}
}
private static List<serviceRecord> GetCollisionRecords (serviceRecord record)
{
return _plan.Where(r => r.serviceStart <= record.serviceStart.Add(record.serviceDuration)
&& r.serviceStart.Add(r.serviceDuration) > record.serviceStart).ToList();
}
private static serviceRecord getNextRecord()
{
DateTime nowdate = DateTime.Now;
if (_plan.Count() == 0) return null;
return _plan
.Where(r => r.serviceStart > nowdate)
.OrderBy(r => r.serviceStart)
.First();
}
private static serviceState getActualState()
{
DateTime nowDateTime = DateTime.Now;
var recordsInProgress = _plan.Where(r => r.serviceStart <= nowDateTime
&& r.serviceStart.Add(r.serviceDuration) > nowDateTime).Count();
if (recordsInProgress >0)
{ return serviceState.OnService; }
else
{ return serviceState.Normal; }
}
}
}
}
namespace LaretsState
{
[DataContract]
public class serviceRecord
{
private static int lastid = 0;
[DataMember]
public DateTime serviceStart;
[DataMember]
public TimeSpan serviceDuration;
[DataMember]
public readonly DateTime creationTime;
[DataMember]
public readonly int id;
public serviceRecord (DateTime serviceStart, TimeSpan serviceDuration)
:this()
{
this.serviceStart = serviceStart;
this.serviceDuration = serviceDuration;
}
public serviceRecord()
{
this.creationTime = DateTime.Now;
this.id = ++lastid;
}
}
}
Is it somthing wrong with a classes?
I found! In serviceRecord class I must use properties, not fields:
[DataMember]
public DateTime serviceStart { get; set; }
[DataMember]
public TimeSpan serviceDuration { get; set; }
[DataMember]
public DateTime creationTime { get;}
[DataMember]
public int id { get;}

MVC Model attribute to HTML attribute

Is there are anyway to embed attribute to html input tag that has set in the model?
Code
[Required]
[StringLength(20)]
public string Username { get; set; }
[Required]
[StringLength(20)]
[DataType(DataType.Password)]
public string Password { get; set; }
Expected Render Ouput:
<input id="Username" name="Username" maxlength="20" type="text" required="required" />
<input id="Password" name="Password" maxlength="20" type="password" required="required" />
I don't want JavaScript validation I want HTML validation
Yes there is a way but you will have to do the customization yourself
You can take a look at the source code of how they implemented it using HtmlHelper extensions
http://aspnetwebstack.codeplex.com/SourceControl/changeset/view/5cb74eb3b2f3#src/System.Web.Mvc/Html/InputExtensions.cs
You're going to need to look at the following to get what you want for the two inputs referenced above
For the Text input
MvcHtmlString TextBoxFor<TModel, TProperty>(...);
For the Password imput
MvcHtmlString PasswordFor<TModel, TProperty>(...);
They primarily use the following helper to construct the markup
// Helper methods
private static MvcHtmlString InputHelper(HtmlHelper htmlHelper, InputType inputType, ModelMetadata metadata, string name, object value, bool useViewData, bool isChecked, bool setId, bool isExplicitValue, string format, IDictionary<string, object> htmlAttributes)
{
string fullName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);
if (String.IsNullOrEmpty(fullName))
{
throw new ArgumentException(MvcResources.Common_NullOrEmpty, "name");
}
TagBuilder tagBuilder = new TagBuilder("input");
tagBuilder.MergeAttributes(htmlAttributes);
tagBuilder.MergeAttribute("type", HtmlHelper.GetInputTypeString(inputType));
tagBuilder.MergeAttribute("name", fullName, true);
string valueParameter = htmlHelper.FormatValue(value, format);
bool usedModelState = false;
switch (inputType)
{
case InputType.CheckBox:
bool? modelStateWasChecked = htmlHelper.GetModelStateValue(fullName, typeof(bool)) as bool?;
if (modelStateWasChecked.HasValue)
{
isChecked = modelStateWasChecked.Value;
usedModelState = true;
}
goto case InputType.Radio;
case InputType.Radio:
if (!usedModelState)
{
string modelStateValue = htmlHelper.GetModelStateValue(fullName, typeof(string)) as string;
if (modelStateValue != null)
{
isChecked = String.Equals(modelStateValue, valueParameter, StringComparison.Ordinal);
usedModelState = true;
}
}
if (!usedModelState && useViewData)
{
isChecked = htmlHelper.EvalBoolean(fullName);
}
if (isChecked)
{
tagBuilder.MergeAttribute("checked", "checked");
}
tagBuilder.MergeAttribute("value", valueParameter, isExplicitValue);
break;
case InputType.Password:
if (value != null)
{
tagBuilder.MergeAttribute("value", valueParameter, isExplicitValue);
}
break;
default:
string attemptedValue = (string)htmlHelper.GetModelStateValue(fullName, typeof(string));
tagBuilder.MergeAttribute("value", attemptedValue ?? ((useViewData) ? htmlHelper.EvalString(fullName, format) : valueParameter), isExplicitValue);
break;
}
if (setId)
{
tagBuilder.GenerateId(fullName);
}
// If there are any errors for a named field, we add the css attribute.
ModelState modelState;
if (htmlHelper.ViewData.ModelState.TryGetValue(fullName, out modelState))
{
if (modelState.Errors.Count > 0)
{
tagBuilder.AddCssClass(HtmlHelper.ValidationInputCssClassName);
}
}
tagBuilder.MergeAttributes(htmlHelper.GetUnobtrusiveValidationAttributes(name, metadata));
if (inputType == InputType.CheckBox)
{
// Render an additional <input type="hidden".../> for checkboxes. This
// addresses scenarios where unchecked checkboxes are not sent in the request.
// Sending a hidden input makes it possible to know that the checkbox was present
// on the page when the request was submitted.
StringBuilder inputItemBuilder = new StringBuilder();
inputItemBuilder.Append(tagBuilder.ToString(TagRenderMode.SelfClosing));
TagBuilder hiddenInput = new TagBuilder("input");
hiddenInput.MergeAttribute("type", HtmlHelper.GetInputTypeString(InputType.Hidden));
hiddenInput.MergeAttribute("name", fullName);
hiddenInput.MergeAttribute("value", "false");
inputItemBuilder.Append(hiddenInput.ToString(TagRenderMode.SelfClosing));
return MvcHtmlString.Create(inputItemBuilder.ToString());
}
return tagBuilder.ToMvcHtmlString(TagRenderMode.SelfClosing);
}

ASP.NET maintain control state that has collection items

Interesting. I have a control QuickContacts with Contacts collection. When I declare Contacts of type List<Contact> it works perfectly, but when use ContactsList<Contact> which is a Generic that implements IList<T> it gives "Parser Error : Type 'Controls.ContactList'1[[Controls.Contact, Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' does not have a public property named 'Contact'."
Here, this code works perfectly with List<Contact>
[DefaultProperty("Contacts"),
ParseChildren(true, "Contacts"),
ToolboxData("<{0}:QuickContacts runat=server></{0}:QuickContacts>")]
public class QuickContacts : WebControl
{
private List<Contact> contactsList;
[Category("Behavior"),
Description("The contacts collection."),
DesignerSerializationVisibility(
DesignerSerializationVisibility.Content),
PersistenceMode(PersistenceMode.InnerDefaultProperty)]
public List<Contact> Contacts
{
get
{
if (contactsList == null)
{
contactsList = new List<Contact>();
}
return contactsList;
}
}
I want to provide a Contacts collection that maintains state so I replace using List<Contacts> with custom ContactsList that implements IList<T>, IStateManager. When use IList<T> instead of List<T>, it doesn't work. Here is the
public class ContactList<T> : IList<T>, IStateManager
{
Then I use it as following:
[DefaultProperty("Contacts"),
ParseChildren(true, "Contacts"),
ToolboxData("<{0}:QuickContacts runat=server></{0}:QuickContacts>")]
public class QuickContacts : WebControl
{
private ContactList<Contact> contactsList;
[Category("Behavior"),
Description("The contacts collection."),
DesignerSerializationVisibility(
DesignerSerializationVisibility.Content),
PersistenceMode(PersistenceMode.InnerDefaultProperty)]
public ContactList<Contact> Contacts
{
get
{
if (contactsList == null)
{
contactsList = new ContactList<Contact>();
}
return contactsList;
}
}
"Parser Error : Type 'Controls.ContactList'1[[Controls.Contact, Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' does not have a public property named 'Contact'."
Parser Error at <cc1:Contact Name=
<asp:Content ID="Content2" ContentPlaceHolderID="Main" runat="server">
<cc1:QuickContacts ID="QuickContacts1" runat="server" BorderStyle="Solid" BorderWidth="1px">
<cc1:Contact Name="someone" Email="someone#example.com"
Phone="(555) 555-0100" />
I read many posts about List<T> vs IList<T> but that still doesn't answer the question. What difference between List<T> and a class that implements IList<T> which causes this error?
Here is the answer, when reviewed List<T> implementation at Microsoft http://referencesource.microsoft.com
[DebuggerTypeProxy(typeof(Mscorlib_CollectionDebugView<>))]
[DebuggerDisplay("Count = {Count}")]
[Serializable]
public class List<T> : IList<T>, System.Collections.IList, IReadOnlyList<T>
{
It implements System.Collections.IList too. And this was the point.
And here is the full working code.
[DefaultProperty("Contacts"),
ParseChildren(true, ChildrenAsProperties = true, DefaultProperty = "Contacts"),
ToolboxData("<{0}:QuickContacts runat=server></{0}:QuickContacts>")]
public class QuickContacts : WebControl
{
private StateManagedCollection<Contact> contactsList;
[Category("Behavior"),
Description("The contacts collection."),
DesignerSerializationVisibility(
DesignerSerializationVisibility.Content),
PersistenceMode(PersistenceMode.InnerDefaultProperty)]
public StateManagedCollection<Contact> Contacts
{
get
{
if (contactsList == null)
{
contactsList = new StateManagedCollection<Contact>();
}
return contactsList;
}
}
protected override void RenderContents(HtmlTextWriter writer)
{
Table t = CreateContactsTable();
if (t != null)
{
t.RenderControl(writer);
}
}
private Table CreateContactsTable()
{
Table t = null;
if (contactsList != null && contactsList.Count > 0)
{
t = new Table();
foreach (Contact item in contactsList)
{
Contact aContact = item as Contact;
if (aContact != null)
{
TableRow row = new TableRow();
TableCell c1 = new TableCell();
c1.Text = aContact.Name;
row.Controls.Add(c1);
TableCell c2 = new TableCell();
c2.Text = aContact.Email;
row.Controls.Add(c2);
TableCell c3 = new TableCell();
c3.Text = aContact.Phone;
row.Controls.Add(c3);
t.Controls.Add(row);
}
}
}
return t;
}
protected override void LoadViewState(object savedState)
{
if (savedState != null)
{
Pair p = savedState as Pair;
base.LoadViewState(p.First);
contactsList.LoadViewState(p.Second);
}
}
protected override object SaveViewState()
{
Pair p = new Pair(base.SaveViewState(), contactsList.SaveViewState());
return p;
}
protected override void TrackViewState()
{
base.TrackViewState();
contactsList.TrackViewState();
}
}
And here is the StateManagedCollection
public class StateManagedCollection<T> : IList<T>, System.Collections.IList, IReadOnlyList<T>, IStateManager
where T : StateManagedClass, new()
{
private List<T> lst = default(List<T>);
private Boolean isTrackingViewState = default(Boolean);
private Boolean saveAll = default(Boolean);
public StateManagedCollection()
{
lst = new List<T>();
isTrackingViewState = false;
saveAll = false;
}
public void SetMarked()
{
for (int i = 0; i < lst.Count; i++)
{
lst[i].SetMarked();
}
}
public bool IsTrackingViewState
{
get { return isTrackingViewState; }
}
public void LoadViewState(object state)
{
if (state != null)
{
if (state is List<Object>)
{
// all items were saved
List<Object> allItems = (List<Object>)state;
saveAll = true;
Int32 count = lst.Count;
for (int i = 0; i < allItems.Count; i++)
{
if (i < count)
lst[i].LoadViewState(allItems[i]);
else
{
T item = new T();
item.LoadViewState(allItems[i]);
lst.Add(item);
}
}
}
else if (state is Dictionary<Int32, Object>)
{
Dictionary<Int32, Object> changedItems = (Dictionary<Int32, Object>)state;
foreach (KeyValuePair<Int32, Object> item in changedItems)
{
if (item.Key < lst.Count)
lst[item.Key].LoadViewState(item.Value);
}
}
}
}
public object SaveViewState()
{
if (saveAll)
{
List<Object> allItems = new List<Object>();
foreach (var item in lst)
{
item.SetMarked();
allItems.Add(item.SaveViewState());
}
return allItems;
}
else
{
Dictionary<Int32, Object> changedItems = new Dictionary<Int32, Object>();
for (int i = 0; i < lst.Count; i++)
{
Object state = lst[i].SaveViewState();
if (state != null)
{
changedItems.Add(i, state);
}
}
return changedItems;
}
}
public void TrackViewState()
{
isTrackingViewState = true;
for (int i = 0; i < lst.Count; i++)
{
lst[i].TrackViewState();
}
}
public int IndexOf(T item)
{
return lst.IndexOf(item);
}
public void Insert(int index, T item)
{
lst.Insert(index, item);
if (isTrackingViewState)
saveAll = true;
}
public void RemoveAt(int index)
{
lst.RemoveAt(index);
if (isTrackingViewState)
saveAll = true;
}
public T this[int index]
{
get
{
return lst[index];
}
set
{
lst[index] = value;
}
}
public void Add(T item)
{
lst.Add(item);
if (isTrackingViewState)
saveAll = true;
}
public void Clear()
{
lst.Clear();
if (isTrackingViewState)
saveAll = true;
}
public bool Contains(T item)
{
return lst.Contains(item);
}
public void CopyTo(T[] array, int arrayIndex)
{
lst.CopyTo(array, arrayIndex);
}
public int Count
{
get { return lst.Count; }
}
public bool IsReadOnly
{
get { return false; }
}
public bool Remove(T item)
{
Boolean rslt = lst.Remove(item);
if (isTrackingViewState)
saveAll = true;
return rslt;
}
public IEnumerator<T> GetEnumerator()
{
return lst.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public int Add(object value)
{
Add((T)value);
return Count - 1;
}
public bool Contains(object value)
{
return Contains((T)value);
}
public int IndexOf(object value)
{
return IndexOf((T)value);
}
public void Insert(int index, object value)
{
Insert(index, (T)value);
}
public bool IsFixedSize
{
get { return ((IList)lst).IsFixedSize; }
}
public void Remove(object value)
{
Remove((T)value);
}
object IList.this[int index]
{
get
{
return lst[index];
}
set
{
lst[index] = (T)value;
}
}
public void CopyTo(Array array, int index)
{
CopyTo((T[])array, index);
}
public bool IsSynchronized
{
get { return ((ICollection)lst).IsSynchronized; }
}
public object SyncRoot
{
get { return ((ICollection)lst).SyncRoot; }
}
}
And the StateManagedClass
public abstract class StateManagedClass : IStateManager
{
private Boolean isTrackingViewState = default(Boolean);
private StateBag viewState = default(StateBag);
public StateManagedClass()
{
isTrackingViewState = false;
viewState = new StateBag(false);
}
public virtual StateBag ViewState
{
get
{
return viewState;
}
}
public bool IsTrackingViewState
{
get { return isTrackingViewState; }
}
public void LoadViewState(object state)
{
if (state != default(object))
{
((IStateManager)viewState).LoadViewState(state);
}
}
public object SaveViewState()
{
Object savedState = default(Object);
if (viewState != null)
{
savedState =
((IStateManager)viewState).SaveViewState();
}
return savedState;
}
public void TrackViewState()
{
isTrackingViewState = true;
if (viewState != default(StateBag))
{
((IStateManager)viewState).TrackViewState();
}
}
public void SetMarked()
{
viewState.SetDirty(true);
}
}
And the Contact class
public class Contact : StateManagedClass
{
[
Category("Behavior"),
DefaultValue(""),
Description("Name of contact"),
NotifyParentProperty(true)
]
public String Name
{
get
{
Object s = ViewState["Name"];
return (s == null) ? String.Empty : (String)s;
}
set
{
ViewState["Name"] = value;
}
}
[
Category("Behavior"),
DefaultValue(""),
Description("Email address of contact"),
NotifyParentProperty(true)
]
public String Email
{
get
{
Object s = ViewState["Email"];
return (s == null) ? String.Empty : (String)s;
}
set
{
ViewState["Email"] = value;
}
}
[
Category("Behavior"),
DefaultValue(""),
Description("Phone number of contact"),
NotifyParentProperty(true)
]
public String Phone
{
get
{
Object s = ViewState["Phone"];
return (s == null) ? String.Empty : (String)s;
}
set
{
ViewState["Phone"] = value;
}
}
}
Test the control:
<%# Page Title="" Language="C#" MasterPageFile="~/RTL.Master" AutoEventWireup="true" CodeBehind="WebForm15.aspx.cs" Inherits="Controls.WebForm15" %>
<%# Register Assembly="Controls" Namespace="Controls" TagPrefix="cc1" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="Main" runat="server">
<cc1:QuickContacts ID="QuickContacts1" runat="server" BorderStyle="Solid" BorderWidth="1px">
<cc1:Contact Name="someone" Email="someone#example.com"
Phone="(555) 555-0100" />
<cc1:Contact Name="jae" Email="jae#fourthcoffee.com"
Phone="(555) 555-0101" />
<cc1:Contact Name="lene" Email="lene#contoso.com"
Phone="(555) 555-0102" />
</cc1:QuickContacts>
<br />
<asp:Button runat="server" ID="Button1" Text="Add" OnClick="Button1_Click"></asp:Button>
<asp:Button runat="server" Text="Refresh"></asp:Button>
<br />
<br />
<asp:HyperLink ID="HyperLink1" NavigateUrl="~/WebForm15.aspx"
runat="server">
Reload Page</asp:HyperLink>
</asp:Content>
<asp:Content ID="Content3" ContentPlaceHolderID="script" runat="server">
</asp:Content>
And the codebehind:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace Controls
{
public partial class WebForm15 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button1_Click(object sender, EventArgs e)
{
SkolaControlsWorkings.Controls.Contact contact = new SkolaControlsWorkings.Controls.Contact();
contact.Name = "Name";
contact.Email = "Email#mai.com";
contact.Phone = "(111) 111-1111";
QuickContacts1.Contacts.Add(contact);
Button1.Visible = false;
}
}
}
Now you can see how pressing the "Add" button causes new contact item to be added to the list, and how the new added contacts are maintained through page postbacks.
This is should be a complete working example, have fun.
Here is the MSDN original example Web Control Collection Property Example

How much of MembershipProvider do I *have* to override in MVC3

Until now I have done all authentication work in my MVC3 app, i.e. validate a member, and create a member, through my MemberRepository class. I would now like to go official, with a custom MembershipProvider. So far I have only gleaned that I really need to override this class's ValidateUser method, and since I am not using a Login control, I'm not even sure I absolutely have to do this.
Overriding methods like GetUser and CreateUser brings uninvited types to my party, like MembershipUser, where I have a finely crafted Member class. Please can someone clear up for me whether or not I really need a custom membership provider, if I'm not going to use any built-in controls or the admin tool, and if I do, should I confine my overrides to the absolutely necessary, which is what?
Here's one I wrote for unit testing. It's about as minimal as can be.
public class MockMembershipProvider : MembershipProvider
{
public IList<MembershipUser> Users { get; private set; }
private string _applicationName;
public override string ApplicationName
{
get
{
return _applicationName;
}
set
{
_applicationName = value;
}
}
public override bool ChangePassword(string username, string oldPassword, string newPassword)
{
throw new NotImplementedException();
}
public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer)
{
throw new NotImplementedException();
}
public override MembershipUser CreateUser(
string username,
string password,
string email,
string passwordQuestion,
string passwordAnswer,
bool isApproved,
object providerUserKey,
out MembershipCreateStatus status)
{
var user = new MembershipUser(ProviderName, username, username, email, passwordQuestion, null, isApproved, false, DateTime.Now, DateTime.Now, DateTime.Now, DateTime.Now, DateTime.Now);
Users.Add(user);
status = MembershipCreateStatus.Success;
return user;
}
public override bool DeleteUser(string username, bool deleteAllRelatedData)
{
var u = Users.Where(mu => mu.UserName.Equals(username, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
if (u == null) return false;
Users.Remove(u);
return true;
}
public override bool EnablePasswordReset
{
get { return false; }
}
public override bool EnablePasswordRetrieval
{
get { return false; }
}
public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
{
throw new NotImplementedException();
}
public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
{
var users = (from u in Users
where u.UserName.Equals(usernameToMatch, StringComparison.OrdinalIgnoreCase)
select u).ToList();
totalRecords = users.Count;
return ToMembershipUserCollection(users);
}
public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
{
var list = Users.Skip(pageIndex * pageSize).Take(pageSize);
totalRecords = list.Count();
var result = new MembershipUserCollection();
foreach (var u in list)
{
result.Add(u);
}
return result;
}
public override int GetNumberOfUsersOnline()
{
return Users.Count();
}
public override string GetPassword(string username, string answer)
{
throw new NotImplementedException();
}
public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
{
return (from u in Users
where u.ProviderUserKey.ToString() == providerUserKey.ToString()
select u).FirstOrDefault();
}
public override MembershipUser GetUser(string username, bool userIsOnline)
{
return (from u in Users
where u.UserName.Equals(username, StringComparison.OrdinalIgnoreCase)
select u).FirstOrDefault();
}
public override string GetUserNameByEmail(string email)
{
return (from u in Users
where u.Email.Equals(email, StringComparison.OrdinalIgnoreCase)
select u.UserName).FirstOrDefault();
}
public override int MaxInvalidPasswordAttempts
{
get { return 3; }
}
public override int MinRequiredNonAlphanumericCharacters
{
get { return 1; }
}
public override int MinRequiredPasswordLength
{
get { return 6; }
}
public override int PasswordAttemptWindow
{
get { return 10; }
}
public override MembershipPasswordFormat PasswordFormat
{
get { throw new NotImplementedException(); }
}
public override string PasswordStrengthRegularExpression
{
get { return null; }
}
public override string Name
{
get
{
return ProviderName;
}
}
public string ProviderName { get; set; }
public override string ResetPassword(string username, string answer)
{
throw new NotImplementedException();
}
public override bool RequiresQuestionAndAnswer
{
get { return false; }
}
public override bool RequiresUniqueEmail
{
get { return true; }
}
private MembershipUserCollection ToMembershipUserCollection(IEnumerable<MembershipUser> users)
{
var result = new MembershipUserCollection();
foreach (var u in users)
{
result.Add(u);
}
return result;
}
public override bool UnlockUser(string userName)
{
return true;
}
public override void UpdateUser(MembershipUser user)
{
var oldUser = Users.Where(u => u.UserName.Equals(user.UserName, StringComparison.OrdinalIgnoreCase)).Single();
var index = Users.IndexOf(oldUser);
Users[index] = user;
}
public override bool ValidateUser(string username, string password)
{
throw new NotImplementedException();
}
public MockMembershipProvider()
{
this.ProviderName = "MockMembershipProvider";
Users = new List<MembershipUser>();
}
}
public class FakeMembershipProvider : MockMembershipProvider
{
public FakeMembershipProvider(string name)
{
this.ProviderName = name ?? "MockMembershipProvider";
}
public override MembershipUser CreateUser(
string username,
string password,
string email,
string passwordQuestion,
string passwordAnswer,
bool isApproved,
object providerUserKey,
out MembershipCreateStatus status)
{
status = MembershipCreateStatus.ProviderError;
var user = new MockMembershipUser();
user.Password = password;
user.User = username;
user.UserKey = providerUserKey;
Users.Add(user);
status = MembershipCreateStatus.Success;
return user;
}
}
public class MockMembershipUser : MembershipUser
{
public string Password { get; set; }
public string User { get; set; }
public object UserKey { get; set; }
public override string UserName { get { return User; } }
public override string Comment { get; set; }
public override object ProviderUserKey { get { return UserKey; } }
public override string GetPassword()
{
return Password ?? string.Empty;
}
Custom MembershipProvider
It is possible to get some nice security features "for free" if you're using a MembershipProvider: You can set up web.config to redirect every non-authenticated user to a login page, for instance. Or you can set up specific parts of the site to only be visible to users with specific roles. If these features don't make sense for your project, or if you're already implementing their equivalent in another way, there's not much point implementing a custom MembershipProvider.
SqlMembershipProvider
One other possibility you may want to consider is actually switching your own implementation to use the SqlMembershipProvider to handle membership functions.
The SqlMembershipProvider provides a robust, proven platform for the common tasks that are annoying to have to reinvent for every project: account creation, validation, deletion, locking, password resets, basic roles, etc. If you've already done all of this yourself without using the SqlMembershipProvider, there really isn't any point creating one just for the sake of having it. However, you should be careful, because there's a good chance that you've done something wrong in your own implementation. For example,
Are you storing passwords as plain text, or as hashes?
Are you open to Rainbow Table attacks, or are you salting your hashes?
Do you lock people's accounts after you've seen 50 or so invalid password attempts in a row, or do you let hackers just keep pounding away until they've brute-forced their way into someone's account?
The SqlMembershipProvider has already addressed all these issues in an easily configurable manner. You may want to have your own membership interfaces and DTOs simply wrap this default MembershipProvider just so you don't have to worry about these various concerns. That way, most of your code doesn't have to interact with these "uninvited types," but you still get the advantages of a widely-used and proven security framework on the back end.
Do you want to decouple your web application from MembershipRepository?
If so, implement all of the same functionality in a custom MembershipProvider so that your app will only depend on the .NET Membership classes (aside from your web.config).
If not, then don't bother.

ASP.NET DynamicData Validate Custom Image FieldTemplate

I've created a custom Image Field Template which works fine. I decided to create some kind of validation for image sizes so I've created a custom validation attribute. here is the code:
public class ImageSizeValidator : ValidationAttribute
{
public long MaxSize { get; set; }
public long MinSize { get; set; }
public override bool IsValid(object value)
{
if (value == null)
return true;
byte[] image = (byte[]) value;
if (image.Length / 1024L > MaxSize || image.Length / 1024L < MinSize)
return false;
return true;
}
}
and here is my FieldTemplate Image_Edit.ascx:
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="Image_Edit.ascx.cs" Inherits="RastinArgham.CRM.Web.DynamicData.FieldTemplates.Image_Edit" %>
<asp:FileUpload ID="FileUpload1" runat="server" OnDataBinding="FileUpload1DataBinding" />
<asp:RequiredFieldValidator runat="server" ID="RequiredFieldValidator1" CssClass="DDControl DDValidator" ControlToValidate="FileUpload1" Display="Static" Enabled="false" />
<asp:DynamicValidator runat="server" ID="DynamicValidator1" CssClass="DDControl DDValidator" ControlToValidate="FileUpload1" Display="Static" />
and here is Image_Edit.ascx.cs:
public partial class Image_Edit : System.Web.DynamicData.FieldTemplateUserControl
{
protected void Page_Load(object sender, EventArgs e)
{
SetUpValidator(RequiredFieldValidator1);
SetUpValidator(DynamicValidator1);
}
protected override void ExtractValues(IOrderedDictionary dictionary)
{
if (FileUpload1.PostedFile == null || String.IsNullOrEmpty(FileUpload1.PostedFile.FileName) || FileUpload1.PostedFile.InputStream.Length == 0)
return;
dictionary[Column.Name] = FileUpload1.FileBytes;
}
public override Control DataControl
{
get
{
return FileUpload1;
}
}
}
and finally my entity meta data class:
[Display(Name = "ServicePhoto", Order = 410, GroupName = "Misc")]
[HideColumnIn(PageTemplate.List)]
[UIHint("Image")]
[ImageSizeValidator(ErrorMessage = "Invalid Photo Size", MinSize = 30, MaxSize = 300)]
public object ServicePhoto { get; set; }
There are two problems:
1- when IsValid(object value) called value is always null!
2- when trying to upload a new image I always get "The value is not valid" Error on client side of
validation.

Resources