ASP.NET CustomControl - RenderControl on a Attribute value - asp.net

I would like to add a attribute to a custom control to extend it's feature.
<ns:PasswordChange
runat="server"
ID="pwch"
UserId='<%# ResidentId %>' />
In the code ..
[ToolboxData("<{0}:PasswordChange runat=server />")]
public class PasswordChange : WebControl
{
public string UserId { get; set; }
public override void RenderControl(HtmlTextWriter writer)
{
writer.Write("<script type=\"text/javascript\">");
writer.Write(script.Replace("{0}",***ajaxCall***));
writer.Write("</script>");
}
......
The parameter ajaxCall above contain the result of the evaulated if (string.IsNullOrEmpty(this.UserId)). That evaluation simply add one ajax-URL if there are a UserId, if not, another url.
The problem is that UserId isn't loaded at the time of RenderControl. It's not so surprising because this is the code that tells the user that UserId is an available attribute at all.
I would like some help/advice how I solve this kind of problem. The attribute is of course there for behavior of the control. I'm not superfamiliar with the execution-model of those controls.

I would try adding a LiteralControl during rendering, and populate it on PreLoad based on the value of UserID.

Related

Scaffold DynamicData dropdown in web application from EF source

I want to scaffold a basic insert form which has dropdowns for the foreign keys.
I cant seem to figure out how to do this. When creating the metadata all the MetaColumns are of type MetaColumns, and none of type MetaForeignKeyColumns - which means that it renders textboxes for all properties - and no dropdown lists.
UIHints seem ineffective. I am using entity framework code first. How do I go about making those textboxes into dropdowns? In fact, I think the MetaData property is not being created ( I am probably missing something here ).
AddPermission.aspx (form only)
<asp:FormView runat="server" ID="AddPermissionForm"
ItemType="Common.Models.tag_permission"
InsertMethod="AddPermissionsForm_InsertItem" DefaultMode="Insert"
RenderOuterTable="false" OnItemInserted="AddPermissionForm_ItemInserted">
<InsertItemTemplate>
<fieldset>
<ol>
<asp:DynamicEntity runat="server" Mode="Insert" EnableViewState="true" ></asp:DynamicEntity>
</ol>
<asp:Button class="btn btn-primary" runat="server" Text="Insert" CommandName="Insert" />
<asp:Button class="btn btn-default" runat="server" Text="Cancel" CausesValidation="false" OnClick="CancelButton_Click" />
</fieldset>
</InsertItemTemplate>
tag_permission.cs ( part of code first model )
public partial class tag_permission
{
[ScaffoldColumn(false)]
public short tp_tag_permission_id { get; set; }
//foreign key one
public string tp_security_group_id { get; set; }
//foreign key two
public short tp_tag_id { get; set; }
[Display(Name = "View")]
public Nullable<bool> tp_vis { get; set; }
}
I might have to use a DynamicDataManager or something, but I'm not sure where to find how or if it should be used on this page alongside the formview.
I've also attached screenshots comparing the rendering of Default_Insert.aspx.cs in my web app, and a basic DynamicData website - almost out of the box from template. In the below pictures, the MetaTable Table property is being inspected in DynamicData/Default_Insert.ascx.cs.
The later image has an incomplete MetaTable property. It has null values for the DataContextType and DataContextPropertyName, and ForeignKeyColumnNames. I'd really like to set the MetaTable on the FormView properly
For reference: The code from the images below is
public partial class Default_InsertEntityTemplate : System.Web.DynamicData.EntityTemplateUserControl {
private MetaColumn currentColumn;
protected override void OnLoad(EventArgs e) {
foreach (MetaColumn column in Table.GetScaffoldColumns(Mode, ContainerType)) {
currentColumn = column;
Control item = new DefaultEntityTemplate._NamingContainer();
EntityTemplate1.ItemTemplate.InstantiateIn(item);
EntityTemplate1.Controls.Add(item);
}
}
...
DynamicData Web Site
My Web Application
Theres a few parts to this one:
On startup, I registered the dynamic data provider in global.asax
Global.asax.cs / other
App.DefaultModel.RegisterContext(
new Microsoft.AspNet.DynamicData.ModelProviders.EFDataModelProvider(() => new MyDbContext()),
new ContextConfiguration { ScaffoldAllTables = true });
App.cs ( a static class I use to store permanent references )
public static class App
...
private static MetaModel s_defaultModel = new MetaModel();
public static MetaModel DefaultModel
{get{ return s_defaultModel; }}
}
then on the page where I want to get the meta data I can do this
ModelMetaTable meta = App.DefaultModel.GetTable( nameof(db.MyAwsomeName) );
and then set the metadata
MyAwesomeForm.SetMetaTable(table);
and then the form will render will all foreign keys / navigation properties as they would in a dynamic data website.
All the properties of the ModelMetadata are then set and populated as you would expect - eg with the DataContext and ForeignKeyName are no longer null

send custom parameters to user control ascx

I need to use user controls (.ascx) on a page, it's a related post user control based in 2 parameters:
1. Current post
2. Relation type
the page needs to have 3 different instances of this control, each having the same Current post parameter, but different relation type (title, author, genre).
The 1st parameter I can get it through url, but what about the second parameter?
I've been googling for a while but i haven't found an answer yet. How can I pass the second parameter so the control can load the information based on these parameters?
I'd rather not to create a control for each parameter, else would be better to build no user control but direct into code :(
Thanks!
Create public properties of the user-control like:
public partial class SampleUC : UserControl
{
public string CurrentPost {get;set;}
public string RelationType {get;set;}
//...
//...
}
Assign those from the page using it either from markup like:
<%# Register TagPrefix="cc" TagName="SampleUC" Src="SampleUC.ascx" %>
...
...
<cc:SampleUC id="myUC" runat="server" CurrentPost="Sample Post Title" RelationType="Title" />
or from code-behind (of the page using it):
protected void Page_Load(object sender, EventArgs e)
{
//...
myUC.CurrentPost = "Sample Post Title";
myUC.RelationType = "Title" ;
//...
}

Display all HTML elements based on Role - Need Optimized Solution

I'm using ASP.Net for web development. I've situation here. say I've many HTML/ASP.Net controls on my page, and I've to set visibility of each control based on Logged-in user's role. for this I'm doing as follows:
Storing each Function-Name and Role combination is DB
During render, checking for role permission for each HTML/ASP.Net control.
e.g: Displaying something like this:
<asp:Label runat="server" id="Lbl1" visible='<%=CheckVisibility("Display","Admin")%>'>
public bool CheckVisibility(string FunctionName, string RoleName){
// checks for db entry and returns bool value
}
Problem is, I've to do this for all the Controls. Is there any other optimized approach available to do this? please help me
Given only your description of what you're trying to solve, I would suggest you create your own controls which inherit from the built-in ones and add some properties to them. Then the controls can do the visibility check themselves. Something like
namespace StackOverflowTest
{
public class Label : System.Web.UI.WebControls.Label
{
public string DisplayRoles { get; set; }
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
Visible = PermissionHelper.CheckPermission("Display", DisplayRoles.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries));
}
}
public static class PermissionHelper
{
public static bool CheckPermission(string function, string[] allowedRoles)
{
// TODO: hit some sort of cache, so you don't make a bajillion queries to the DB
return true;
}
}
}
And then if you put this in your web.config (sorry, can't figure out how to do proper XML formatting here): <system.web>
<pages>
<controls>
<add tagPrefix="sot" assembly="StackOverflowTest" namespace="StackOverflowTest"/>
</controls>
</pages>
</system.web>
You can add this to your markup:
<sot:Label ID="AdminLabel" runat="server" Text="Bind this in OnLoad/!IsPostback or something" DisplayRoles="Admin,Management" />
This is just one of the many ways you can do this. It all depends on the requirements, of course. But I'm pretty sure you'll need your own classes for controls to have the possibility of making it manageable.
C# code:
public enum previlageType
{
superAdminPrevilages=1,
partnerPrevilages = 2,
dealerPrevilages = 3,
customerPrevilages=4
}
if ((previlageType)Enum.Parse(typeof(previlageType), Session["previlageType"].ToString())== previlageType.partnerPrevilages)
{
accordion.Visible = false;
}
ASP code:
<div id="accordion" runat="server">
Hello World, I'l be Hidden if a person with partner previlages is logged in. BUt will be visible if superadmin or any person except Partner logs in.
</div>
Hope it helps
If you're using a master page, you could get all the child page controls on load (get contentplaceholders, then get contentplaceholder controls).
Then when you have all the control names, do a lookup on your table and set its visibility to false if needed.
(below is vb but the translation should be easy.)
For Each cp As String In Me.ContentPlaceHolders
For Each ctl As Control In Me.FindControl(cp).Controls
If adminonly.Contains(ctl.ID) Then
ctl.Visible = False
End If
Next
Next

Using ASP.NET Server Controls in MVC?

On my current project I need to add a functionality that allows the user to view a thumbnail of their uploaded PDF. I've found a handy component that achieves this (the basic version is free, but it's enough for my current needs). Anyways, the control is pretty outdated (2010), therefore there doesn't seem to be MVC support. On the demos they depict usage of the control as such:
The View's Markup:
<form method="post" runat="server" enctype="multipart/form-data">
<asp:Panel ID="thumbnailsPanel" runat="server" />
</form>
The thumbnail control is instantiated via code, the byte array which represents the thumbnail is passed to the control and the control is added to thumbnailsPanel
<script runat="server">
protected void DisplayThumbs_Click( object sender, System.EventArgs e )
{
Thumbnail thumbnail = new Thumbnail();
thumbnail.SessionKey = sessionID;
thumbnail.Index = i;
thumbnailsPanel.Controls.Add( thumbnail );
}
</script>
Given that I can't declare a Thumbnail control in my razor view, how would I used this control in MVC? I've spent a few hours trying to make this control MVC friendly to no avail, the best I've come up with is to include a .ASPX view (not.cshtml) in my project and render the Thumbnail control on that view. Obviously this is not desirable.
So how would you go about using a ASPX server controls in MVC? Is the idea a bad one altogether and should not be practised?
I worked around it in a project of mine by reimplementing the control as a HtmlHelper. Assuming the control isn't too complicated then it should work for you too. Do this:
Dump the Control's source using Reflector
Massage the source so it actually compiles (as source from Reflector doesn't usually compile straight away)
Identify what state the control has. Convert the state from member properties into members of its own new ViewModel class.
Find the Render method and convert it to a HtmlHelper that uses ViewContext.Writer
For example:
public class FooControl : Control {
public String Message { get; set; }
public override void Render(HtmlTextWriter wtr) {
wtr.WriteLine("<p>");
wtr.WriteLine( message );
wtr.WriteLine("</p>");
}
}
Becomes this:
public class FooViewModel {
public String Message { get; set; }
}
// This method should exist in a static Extensions class for HtmlHelper
public static void Foo(this HtmlHelper html, FooViewModel model) {
HtmlTextWriter wtr = html.ViewContext.Writer;
wtr.WriteLine("<p>");
wtr.WriteLine( model.Message );
wtr.WriteLine("</p>");
}

ASP.NET ASCX Use of Instance Variable

Let's say I have an ASCX user control that requires access to the current user's full name. An ASPX page contains this line at the top
<%# Register src="top.ascx" tagprefix="custom" tagname="top" %>
and this line in the body:
<custom:top runat="server" />
The ASPX file knows the user ID of the current user and could determine his full name. So how can I use the code run by the ASPX file to provide its information to the ASCX file?
Declare a property on the UserControl and have the parent page set it.
On your usercontrol:
public string FullName { get; set; }
On the aspx page either set it in the code behind
YourUserControl.FullName = FullName
or through markup
<custom:top runat="server" FullName="<%= SomeProperty %>" />
You could use the Page property of the user control and cast it to the instance of your page. Then, call the method of your page class to get the user name.
To make this work in a dynamically compiled project, you have to do a little more work to have the control recognize the data type of the dynamically compiled page. Here is a short tutorial on how to do.
Or, as Brandon outlines, do the opposite and let your page tell your user control the information.
This sounds like you might be mistaken about how the page lifecycle works and how you can expose data across your controls. For example, lets say you have this code in your ASPX:
public override void OnLoad(EventArgs e)
{
string userName = "Bob";
}
In your ASPX file, you can reference the control and set a property on it to pass the data along:
<custom:top ID="someControl" runat="server" />
You expose a property in your top control like so:
public string UserName { get; set; }
You could then add this code to your OnLoad method:
someControl.UserName = userName;
Then your control will have access to that data. Alternatively, you can stick things in the Request cache if you dont have a direct line to the control:
HttpContext.Current.Items["key"] = userName;
And then pull the data from your control via the same fashion:
string fromCache = HttpContext.Current.Items["key"];
You could go about this in several ways. I typically use a session variable, since the user will be bound to the session.
In the ASPX (or when the user logs in):
Session["UserFullName"] = GetFullName(); //Code to get full name here
In the ASMX:
this.FullName = Session["UserFullName"]; //TODO: Check for null values

Resources