class MyListControl : DropDownList {
public override object DataSource {
get { return Helper.GetDictionary(); }
set { }
}
public override string DataTextField {
get { return "Key"; }
set { }
}
public override string DataValueField {
get { return "Value"; }
set { }
}
public override void DataBind() {
if (Helper.ConditionSatisfied) {
base.DataBind();
}
}
}
Does ASP.NET ever need to use the set_DataSource()? And are there any references to when get_DataSource() might ever be called more than once (iterating over a collection when the iterator may not be resettable)?
Thank you.
I'm not sure what you mean by does it ever use set_DataSource?
Of course it does for example:
myDropDownBox.DataSource = MyBLLayer.GetSomeDataSet(SomeParams);
myDropDownBox.DataBind();
In the above example MyBLLayer is simply a static class that calls a method which returns some sort of dataset. That dataset could be a List for example.
RequiresDataBinding is protected in the base class hence no overriding of this property. You would not want to override this property in any case as its values are simply True or False.
Related
How can I hide some not virtual properties of parent class in PropertyGridControl without using [Browsable(false)]? I can not use this, because I can not override not virtual properties.
If you cannot override the property then you can use new modifier.
Here is example:
public class SomeChildClass : SomeParentClass
{
[Browsable(false)]
new public TypeOfProperty SomeProperty
{
get { return base.SomeProperty; }
set { base.SomeProperty = value; }
}
}
I have following logic in Admin screen. I need similar logic in Logs screen also. Hence I am planning to move this logic into base page. In base page, how do I recognize the current page? (How do I distinguish between Admin screen and Logs screen?).
Based on the page the value retrieved from the config is different.
What are the different ways to achieve this? What is the best way out of these approaches?
//Admin Screen
List<string> authorizedRoles = new List<string>((ConfigurationManager.AppSettings["AdminScreenRoles"]).Split(','))
if (!authorizedRoles.Contains(userRole))
{
Response.Redirect("UnauthorizedPage.aspx");
}
//Logs Screen
List<string> authorizedRoles = new List<string>((ConfigurationManager.AppSettings["LogsScreenRoles"]).Split(','))
if (!authorizedRoles.Contains(userRole))
{
Response.Redirect("UnauthorizedPage.aspx");
}
Don't put code in base that recognize the class that inherit it. Add an abstract property that the child will have to override.
In base:
public abstract string AppSettingsRolesName { get; }
List<string> authorizedRoles = new List<string>((ConfigurationManager.AppSettings[AppSettingsRolesName]).Split(','))
if (!authorizedRoles.Contains(userRole))
{
Response.Redirect("UnauthorizedPage.aspx");
}
In Logs:
public override string AppSettingsRolesName
{
get { return "LogsScreenRoles"; }
}
In Admin:
public override string AppSettingsRolesName
{
get { return "AdminScreenRoles"; }
}
The easiest way would be to look into forms authentication, as it will handle all of this for you through a configuration file. There are a number of good articles on this dotted around the web - here's one:
http://ondotnet.com/pub/a/dotnet/2003/01/06/formsauthp1.html
However, if you're looking for a quick fix, the easiest way is to move your code into the base page as you said, and use an interface property to make inherited pages indicate what role type to use - e.g. something along the lines of:
public abstract class BasePage : Page
{
protected abstract string AuthorisedRoles { get; }
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
List<string> authorizedRoles = new List<string>((ConfigurationManager.AppSettings[this.AuthorisedRoles]).Split(','));
if (!authorizedRoles.Contains(userRole))
{
Response.Redirect("UnauthorizedPage.aspx");
}
}
}
public class LogsPage : BasePage
{
protected override string AuthorisedRoles
{
get { return "LogsScreenRoles"; }
}
}
public class AdminPagePage : BasePage
{
protected override string AuthorisedRoles
{
get { return "AdminScreenRoles"; }
}
}
But seriously, look into forms authentication if you want to do it properly - it's not as complicated as it first looks.
I have a controller with two render methods that take different arguments:
class MyController
{
#RenderMapping
public void render(#ModelAttribute ClassX param)
{
// do some stuff
}
#RenderMapping
public void render2(#ModelAttribute ClassY param)
{
// do different stuff
}
}
Of course what is missing in the example above is some specification for spring to know which of the render methods to invoke. I need to decide this based on a state stored in the current session. I can't specify this just as a simple annotation, can I?
An alternative idea is something like this:
class MyController2
{
#RenderMapping
public void render(RenderRequest request)
{
if (request.getPortletSession().getAttribute(...) ...)
{
ClassX param = retrieveObjectFromRequest(ClassX.class, request);
// do some stuff
}
else
{
ClassY param = retrieveObjectFromRequest(ClassY.class, request);
// do different stuff
}
}
}
But in this case... How do I implement the retrieveObjectFromRequest method?
OK, after scrolling Spring's source code for a while I figured a way to do the retrieveObjectFromRequest part:
class MyController
{
#RenderMapping
public void render(WebRequest webRequest)
{
ClassX param = new ClassX();
new WebRequestDataBinder(param).bind(webRequest); // Fills param's properties.
}
}
I've build a class like this:
private class TestResults
{
public bool IsAdmitted { get; set; }
public bool IsDuplicate { get; set; }
public bool IsVerified { get; set; }
}
The values of this class are set at postback by clicking a radiobutton list. Problem however is I don't know how to save this values across multiple postbacks. I thought of using viewstate but I'm not quite sure how to do it with this class.
Maybe I'm missing some important thing here.
Hope someone can point me in the right direction
thanks for your time!
Kind regards,
Mark
Just sticking this class in viewstate is pretty simple:
ViewState["SomeUniqueKey"] = myTestResults;
var testResults = (TestResults)ViewState["SomeUniqueKey"];
Your class will need to be marked with the [Serializable] attribute though.
try using the Session cache instead
var testResults = new TestResults();
//set values
Session["TestResults"] = testResults;
Retrieving them later on:
var testResults = Session["TestResults"] as TestResults;
if (testResults != null)
{
//use it
}
You can use
Session.Add("TestResults", Your_Test_Result_Object)
Session Object Explanation
If you don't need this value on other pages or in other places throughout the app, you can use viewstate.
Use the Page.ViewState object bag to store it:
public partial class Page1 : Page {
protected void button1_click(object sender, EventArgs e) {
ViewState["myObject"] = testResultsObject;
}
}
You could also wrap the access to it in a property on the page:
public partial class Page1 : Page {
public TestResults TestResults {
get{ return ViewState["TestResults"] as TestResults; }
set{ ViewState["TestResults"] = value; }
}
}
One example is described here. But the author apparently forgot to include the code for download.
Another example is shown here. However, this one doesn't quite work (as described in comments).
How do you do this correctly?
The second example you found almost works, it's just missing a little bit. All that was needed was 2 methods in the main control.
Add this code to the AppointmentControl.cs file and it will work.
protected override object SaveViewState()
{
if (appointments != null)
return appointments.SaveViewState();
return null;
}
protected override void LoadViewState(object savedState)
{
appointments = new AppointmentCollection();
appointments.LoadViewState(savedState);
}
The code in the example site was pretty decent. It implemented all of the interfaces it should have and did a pretty good job. Where it fell apart was that, despite having all of the code it needed in the abstract bits, that didn't matter because the interfaces weren't referenced in the places they needed to be.
The collection classes being used had nothing "special" about them, other than implementing a few interfaces. The framework won't automatically call these methods. The framework will however call the overridden methods I wrote above, which you need to implement in order for your control to save the elements in the collection. As long as you call them, everything will work.
DanHerbert got it. Darn, I spent hours on this too! In the process of trying to answer this question I came up with a simplified generic StateManagedCollection that inherits from the framework's built-in StateManagedCollection, based on the version here. Maybe you'll find it useful. Full source code of my sample project available here.
using System;
using System.Collections;
using System.Collections.Specialized;
using System.Security.Permissions;
using System.Web;
using System.Collections.Generic;
using System.Web.UI;
namespace Web
{
public abstract class StateManagedCollection<T> : StateManagedCollection, IList<T>, ICollection<T>, IEnumerable<T>
where T : class, IStateManagedItem, new()
{
protected override object CreateKnownType(int index)
{
return Activator.CreateInstance<T>();
}
protected override Type[] GetKnownTypes()
{
return new Type[] { typeof(T) };
}
protected override void SetDirtyObject(object o)
{
((IStateManagedItem)o).SetDirty();
}
#region IList<T> Members
public int IndexOf(T item)
{
return ((IList)this).IndexOf(item);
}
public void Insert(int index, T item)
{
((IList)this).Insert(index, item);
if (((IStateManager)this).IsTrackingViewState)
{
this.SetDirty();
}
}
public void RemoveAt(int index)
{
((IList)this).RemoveAt(index);
if (((IStateManager)this).IsTrackingViewState)
{
this.SetDirty();
}
}
public T this[int index]
{
get { return (T)this[index]; }
set { this[index] = value; }
}
#endregion
#region ICollection<T> Members
public void Add(T item)
{
((IList)this).Add(item);
this.SetDirty();
}
public bool Contains(T item)
{
return ((IList)this).Contains(item);
}
public void CopyTo(T[] array, int arrayIndex)
{
((IList)this).CopyTo(array, arrayIndex);
}
public bool IsReadOnly
{
get { return false; }
}
public bool Remove(T item)
{
if (((IList)this).Contains(item))
{
((IList)this).Remove(item);
return true;
}
return false;
}
#endregion
#region IEnumerable<T> Members
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
throw new NotImplementedException();
}
#endregion
#region IEnumerable Members
IEnumerator IEnumerable.GetEnumerator()
{
return ((IList)this).GetEnumerator();
}
#endregion
}
}
I have used the code above the provided solution is ok but i was getting exception - "StackOverflow " cool :) the issue is reproducible by adding a few child items in the aspx page and switch to Design view to design view of Visual studio ( Visual Studio just restart and nobody knows what is going on....).
IEnumerator IEnumerable.GetEnumerator()
{
return ((IList)this).GetEnumerator();
}
So, I guess I figured it out just change the implementation of the above method like this:
IEnumerator IEnumerable.GetEnumerator()
{
// return ((IList)this).GetEnumerator();
return this.GetEnumerator();
}
Hope this will help someone else like me :) just not to loose few hours to get it work with the designer of VS