I'm developing custom controls with security included. When the user does not have access to the control, the control makes itself disable but also go invisible. The control is not rendered and it does not appear on the page. At this point, everything is fine.
My question is how I can secure the control the prevent user to change the value?
I have injected an input in my form with Chrome HTML Inspector because like it should be, the field is not rendered, when I submit the form with the injected input with a new value, the server has the new value in the control value property.
public enum UserRole {
Standard,
Administrator,
[...]
}
//For this example, my custom control is derived from HtmlInputText. [ToolboxData("<{0}:MyCustomControl runat=\"server\"></{0}:MyCustomControl>")]
public class MyCustomControl: System.Web.UI.HtmlControls.HtmlInputText
{
public UserRole? MinimumRoleRequired { get; set; }
protected override void OnLoad(EventArgs e)
{
//Simplified version
if (this.Page.CurrentUser.Role < this.MinimumRoleRequired)
{
this.Visible = false;
this.Disabled = true;
return;
}
[...]
}
protected override void Render(HtmlTextWriter writer)
{
if (!this.Visible || this.Disabled)
{
return;
}
[...]
}
[...]
}
//My page who contain the control:
//HTML (MyPage.aspx)
<Controls:MyCustomControl ID="tbAdminOnly"runat="server"></Controls:MyCustomControl>
//C# (MyPage.aspx.cs)
public partial class UserEdit : Page
{
protected override void OnInit(EventArgs e)
{
this.tbAdminOnly.MinimumRoleRequired = UserRole.Administrator;
[...]
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (this.IsPostBack)
{
string postBackValue = tbAdminOnly.Value;
return;
}
tbAdminOnly.Value = "Hello world!";
}
}
When I load the page as a standard user, the control is not rendered. But if I inject input in the html page
//Note, i need to know the valid name/id but it could be done.
<input type="text" name="tbAdminOnly" id="tbAdminOnly" value="Damn shit">
The postBackValue is now the new value from the injected input. How I can prevent that?
Thanks.
To prevent user from injecting html controls, you need to sanitize the inputs. There are similar posts. How to use C# to sanitize input on an html page?
Related
How can I extend the class Content Page to create a method that executes when it is the user's first time on a page?
(Xamarin.Forms)
This is probably the simplest way to do it:
public abstract class CustomContentPage : ContentPage
{
private bool _appeared;
protected override void OnAppearing()
{
base.OnAppearing();
if (!_appeared)
{
OnFirstAppearing();
_appeared = true;
}
}
protected abstract void OnFirstAppearing();
}
First you will want to use Application.Properties dictionary so you can preserve the state of the application, i.e. whether the user has ever gone to the page.
So in the OnAppearing method override in your ContentPage subclass, check to see if you have set the property in the Application.Current.Properties dictionary to see if the page has been visited. If the key is not present, set it and do whatever you want for this first visit to the page. If the key is present, do whatever you want to do for subsequent visits to the page, e.g.:
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
protected override void OnAppearing()
{
base.OnAppearing();
if (!Application.Current.Properties.ContainsKey("main_page_visited"))
{
Application.Current.Properties["main_page_visited"] = true;
label.Text = "First Time visited";
}
else
{
label.Text = "Second+ Time visited";
}
}
}
The Application.Current.Properties gets saved automatically when the app exits.
I have a question and I can not find the right terms to do a reasoned search and solve the question.
Let's see, when I'm creating a page, at some point I need to create a WebUserControl and defer something like state = "true" (like the text of the lables) inside the html tag so that as soon as the page loads , Whether or not that control is subsequently edited in code.
<MyControls:Teste Id="aaa" runat="server" state="false"/>
The test control code is as follows: (The HTML page of this control is blank, it only has the header)
public partial class WebUserControls_WUC_Tect : System.Web.UI.UserControl
{
private static bool state ;
public bool State
{
get { return state ; }
set { state = value; }
}
protected void Page_Load(object sender, EventArgs e)
{
}
}
Problem:
Whenever the page returns to the server and is reloaded, the state variable is always set to false or true depending on the initial state I passed, what I intended was for this variable to be loaded only once at the beginning of the page and then Could only be changed by codebeind.
I am grateful for your suggestions.
greetings
Patrick Veiga
You need to use the ViewState to store the property value to keep the persistent value saved.
public partial class WebUserControls_WUC_Tect : System.Web.UI.UserControl
{
private static bool state ;
public bool State
{
get
{
if (ViewState["MyState"] == null)
{
ViewState["MyState"] = false;
}
return (bool)ViewState["MyState"];
}
set
{
ViewState["MyState"] = value;
}
}
protected void Page_Load(object sender, EventArgs e)
{
}
}
I am trying to create a custom component. The component should by dynamically initialized in code behind. The component presents a custom Window containing other components, like datefields, dropdown fields etc. I derived my class from Ext.Net.Window and added simple DateField. The date should than be used by a button click on the server (Date should not be passed over DirectMethod parameter). When I add this component to mark-up it works perfectly. But when I add the window in code behind, the value of the datefield is not set after the server call.
I am creating the window in the life cycle in OnInit event by "Controls.Add(mywindow)". It would be great if anybody could give me a hint. Here my window code (onExecuteButtonClick just calls the direct method and hides the window):
public sealed class WindowFilterComponent:Window
{
private const string Script = "MyProject.JavaScript.src.WindowFilterComponent.js";
public override string InstanceOf
{
get
{
return "MyProject.Filter.WindowFilterComponent";
}
}
public override string XType
{
get
{
return "windowfiltercomponent";
}
}
private Button _btnExecute;
private Button _btnCancel;
private DateField _dateField;
protected override void OnInit(EventArgs e)
{
AutoHeight = true;
_btnExecute = new Button("Execute Export");
_btnExecute.Listeners.Click.Handler = string.Format("#{{{0}}}.onExecuteButtonClick()", ID);
_btnCancel = new Button("Cancel");
_btnCancel.Listeners.Click.Handler = string.Format("#{{{0}}}.onCancelButtonClick()", ID);
Buttons.Add(_btnExecute);
Buttons.Add(_btnCancel);
_dateField = new DateField();
Items.Add(_dateField);
base.OnInit(e);
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (ExtNet.IsAjaxRequest || Page.IsCallback) return;
ResourceManager.GetInstance().AddDirectMethodControl(this);
}
[DirectMethod(ShowMask = true)]
public void ExecuteClick()
{
var date = _dateField.SelectedValue;
}
}
Now the useage in my page in the OnInit event:
protected override void OnInit(EventArgs e)
{
var myWindow = new WindowFilterComponent()
{
Hidden = false,
Width = 500
};
myWindow.ID = myWindow.ID + "MyComponent";
Controls.Add(myWindow);
base.OnInit(e);
}
I think the Window is rendered outside of the Form.
Please replace
Controls.Add(myWindow);
with
Form.Controls.Add(myWindow);
Also I would recommend to set up explicit IDs for the submittable fields (the DateField in your case) to ensure that the id key from POST data will match the control's ID on the server.
In my windows phone 8 app, I am navigating among pages. say
From MainPage(some user control a click to) -> Page1 then with a key press it will take me to main page back again
From MainPage(some user control b click to) -> Page2 and then back with the key press to main page again and so on to page3, page4 etc.
Here I want to identify from which page the main page is loaded from?
Say page1, page2 or page3 based on that I want to load the user controls according to navigation history.
I could not found any built-in property or function in a library.
Any help, I am looking for best practice as well to achieve such functionality.
You can use back stack for this kind of purposes.
How to navigate using the back stack for Windows Phone
See also:
https://stackoverflow.com/a/7000977/942286
make hashtable global.
Hashtable ht = new Hashtable();
ht.Add("page1");
NavigationService.Navigate(new Uri("Page1.xaml", UriKind.Relative));
You can create an
enum PageType
{
NONE,
PAGE_1,
PAGE_2,
PAGE_3,
PAGE_4
}
Then in your MainPage you can have a ivar as
private PageType pageType = PageType.NONE;
Then when you move to a page you can set it
pageType = PageType.PAGE_!;
NavigationService.Navigate(new Uri("Page1.xaml", UriKind.Relative));
and when you come back to MainPage then you can have this
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
if (e.NavigationMode == NavigationMode.Back)
{
switch (pageType)
{
case PageType.NONE:
//Your code
break;
case PageType.PAGE_1:
//Your code
break;
case PageType.PAGE_2:
//Your code
break;
case PageType.PAGE_3:
//Your code
break;
case PageType.PAGE_4:
//Your code
break;
}
}
}
EDIT
You can then use navigation context.
In your user control
NavigationService.Navigate(new Uri("Page1.xaml?PAGE_TYPE=Page1", UriKind.Relative));
In your MainPage
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
if (e.NavigationMode == NavigationMode.Back)
{
String pageType = null;
NavigationContext.QueryString.TryGetValue("PAGE_TYPE", out pageType);
if (pageType == "Page1")
{
//Your code
}
}
}
If you must know what page you came from, you can use PhoneApplicationService.Current.State. Within your secondary pages, override OnBackKeyPress and set the value
protected override void OnBackKeyPress(System.ComponentModel.CancelEventArgs e)
{
base.OnBackKeyPress(e);
PhoneApplicationService.Current.State["LastPage"] = this;
}
Then in the MainPage, you would override OnNavigatedTo and check the value of the state
protected override void OnNavigatedTo(NavigationEventArgs e)
{
object lastPage;
if((e.NavigationMode == NavigationMode.Back) &&
(PhoneApplicationService.Current.State.TryGetValue("LastPage", out lastPage)))
{
// we navigated back and we know what the last page was!
var pageName = lastPage.GetType().Name;
if (pageName == "Page1")
{
// do something!
}
}
}
Just pass parameters when you are navigating back to main page, maybe an enum type contains 'page1' 'page2' ...
It seems that the NavigationService doesn't contain the information you need, as well as the NavigatingCancelEventArgs parameter coming with OnNavigatingFrom.
So unfortunately, it seems there's no builtin feature addressing your need.
However , what you could do is to persist the last page your user has been (to handle tombstoning scenarios). For instance it could be in AppSettings, here is a pseudo code :
public class WhateverYouWantLastPagePersister
{
private const string LastPageID = "LastPage";
public string GetLastPage()
{
string lastPage = string.Empty;
IsolatedStorageSettings.ApplicationSettings.TryGetValue<string>(LastPageID, out lastPage);
return lastPage;
}
public void PersistLastPage(string lastPage)
{
IsolatedStorageSettings.ApplicationSettings[LastPageID] = lastPage;
}
}
To persist "automatically" your last visited page, you can derive from PhoneApplicationPage and override OnNavigatingFrom to create a your own base page :
public class BasePage : PhoneApplicationPage
{
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
base.OnNavigatedFrom(e);
Uri currentUri = ((App)Application.Current).RootFrame.CurrentSource;
WhateverYouWantLastPagePersister.PersistLastPage(CustomMethodToExtractPageNameFromUri(currentUri));
}
}
All pages needing to persist the last visited pages have to derived from it (so Page1, Page2...)
Finally you can use WhateverYouWantLastPagePersister.GetLastPage() to get what you need.
Of course, in these pseudo code samples :
lastPage can be of any type you want (string, enum , int and so
on...), you just need an appropriate custom converter from string to anything you want
CustomMethodToExtractPageNameFromUri is a simple string parser
WhateverYouWantLastPagePersister can be static class, a singleton, injected with a DI framework, it's up to you!
My asp.net application has a custom base user control that is inherited from other user controls. This custom base user control has three properties that have been made public. When the user control is loaded the custom base user control properties are null. I am trying to figure what I am doing wrong. can someone please help figure out what step I am missing?
custom base user control loading code from parent page:
private void Render_Modules()
{
foreach (OnlineSystemPageCustom.OnlineSystemPageHdr.OnlineSystemPageModule item in custompage.Header.Modules)
{
if (item.ModuleCustomOrder != 99)
{
webonlinecustombase ctl = (webonlinecustombase)Page.LoadControl("../IPAM_Controls/webtemplatecontrols/webonlinecustombase.ascx");
ctl.Event = Event;
ctl.custompage = custompage;
ctl.custommodule = item;
this.eventprogrammodules.Controls.Add(ctl);
}
}
}
custom base user control code behind
public partial class webonlinecustombase : System.Web.UI.UserControl
{
public Event Event { get; set; }
public OnlineSystemPageCustom custompage { get; set; }
public OnlineSystemPageCustom.OnlineSystemPageHdr.OnlineSystemPageModule custommodule { get; set; }
public void Page_Load(object sender, EventArgs e)
{
string typeName = custommodule.ModuleInternetFile;
inpagelink.HRef = "#" + custommodule.ModuleName.Replace(" ", "").Replace("/", "");
modtitle.InnerText = custommodule.ModuleName;
Type child = Type.GetType(typeName);
UserControl ctl = (UserControl)Page.LoadControl(child, null);
if (ctl != null)
{
this.modsection.Controls.Add(ctl);
}
}
}
sample code of user control inheriting base user control
public partial class eventscientificoverview : webonlinecustombase
{
protected void Page_Load(object sender, EventArgs e)
{
if (custommodule.ModuleDefaultVerbiage != null && custommodule.ModuleDefaultVerbiage != "") { this.Load_Verbiage(false); }
else if (custommodule.ModuleCustomVerbiage != null && custommodule.ModuleCustomVerbiage != "") { this.Load_Verbiage(true); }
}
protected void Load_Verbiage(bool usecustom)
{
if (usecustom) { this.scientificoverviewverbiage.InnerHtml = custommodule.ModuleCustomVerbiage; }
else { this.scientificoverviewverbiage.InnerHtml = custommodule.ModuleDefaultVerbiage; }
}
}
You must call Render_Modules in the init event of the parent page.
Also, you may want to restructure your base/custom classes to avoid event execution order confusion since the load event will be fired in both the base and the custom classes.
Any time we have this type of structure, we always implement an OnLoad method in the base class for inheritors to override. This way we can control exactly when the Load logic is executed in the inheritors.
Updated with additional info
Here is some additional information on how to handle the load events in base and child classes.
In webonlinecustombase, add the following:
protected virtual void OnPageLoad() {
}
then modify your page load event to call this new method at the appropriate time:
public void Page_Load(object sender, EventArgs e)
{
string typeName = custommodule.ModuleInternetFile;
inpagelink.HRef = "#" + custommodule.ModuleName.Replace(" ", "").Replace("/", "");
modtitle.InnerText = custommodule.ModuleName;
Type child = Type.GetType(typeName);
UserControl ctl = (UserControl)Page.LoadControl(child, null);
if (ctl != null)
{
this.modsection.Controls.Add(ctl);
}
// Now let the inheritors execute their code
OnPageLoad();
}
then, in your inherited class, change:
protected void Page_Load(object sender, EventArgs e)
to
protected override void OnPageLoad()
As I was reviewing this code, I discovered that you are also dynamically loading controls in webonlinecustombase. You will need to move the loading of the controls into the init event in order for them to work correctly in the standard page logic.
Did you try base.[PropertyName] ?
If you have a new keyword or override in your derived class and had only the values in your base class could be the culprit. This has happened to me before.