In a recent post, I expressed a need to access the properties for the body using declarative syntax, see
Contentplaceholder for replacing attributes?
I thought the first suggestion solved my problem. But, the syntax confuses the editor which is not acceptable.
My hypothesis for a workable solution is to make the change in code. To derive a class from System.Web.UI.Page with extended functionality. However, I want for the designer to be able to still use declarative syntax to set the body tag.
In other words,
I do not want to have to change any code in my aspx web pages except that they derive from base
I want to be able to set these properties using declarative syntax, merely by adding a tag in the derived page
I'm not immediately sure how to go about doing this because it doesn't exactly fit the OOP paradigm and I'm not sure where the changes need to be made.
Initial hypothesis,
I can use a findcontrol in the base to see if the placeholder has been added. But, not sure exactly at what point in the page processing lifecycle that I can use this findcontrol. I need to set the body before it renders but also be able to grab something from the declarative code.
I hope what I'm trying to accomplish is clear(?) Basically, I want to be able to edit a user defined tag in my aspx page that will change the class for the body in a master page.
Why not create a custom server control (called something like BodyAttributeManager) that does not render anything, but just looks at its attributes and programatically adds them to the body element on PreRender?
Nested tags as mentioned in that example isn't going to work. ASP.NET does not support that. #jball's suggestion is a good idea; having a class outside of the body that can programmably affect the body's settings from code (which is the only real solution here) would give you what you are looking for.
HTH.
Related
We are using a CMS and I need to alter correct some of the HTML that is being generated by a control that is completely black-boxed. Usually I would sub-class the offending control and tweak it within that, but because of the way the control has been written I am unable to remove the offending attribute.
This leaves me the only option of performing this operation through the Render method on the master page itself. I was thinking of changing the content string before it is rendered, this would involve a bit of Regex in a bid to remove the invalid attribute being rendered.
Given that this operation will run on every page, is this the most efficient way of achieving it? Should I perhaps do a string.Contains() to check for the existance of the HTML element first? Is using Regex for this going to cause performance issues?
First, does this have to run on every page? If so, that is fine, but if you are merely running on every page because it is the solution you have currently in your mind, then it might be better to go back to the business problem at hand.
If you want an architectural decision, "fix before binding" is preferable to "fix in a rendering method". This is regardless of master page or not. I would rather massage a "data set" to using row binding events, as the code shows clearer intent and usually performs better.
I would also consider caching if this is the same content over and over again. If it is not, then why are you using the master page. And "it has a render event" is not a good reason.
Hope this helps.
I'm currently working on an ASP.NET 3.5 project, and I wanted to know your opinion regarding the following situation, which I happen to run into sometimes:
Let's say I've defined the following control of an imaginary component framework somewhere in my code:
<Window runat="server" ID="windowTest" />
Let's assume that with the above mentioned imaginary component framework it's possible to get a reference to my Window control from the client-side using its ID (for example to change its appearance):
function MyFunc(){
var win = GetWindow("windowTest");
}
Let's also assume that both code snippets are placed in different files, e.g. the JavaScript code in MasterPage.Master and the control in AnotherPage.aspx.
As you might already have noticed, the passing of the control's ID as a hard-coded string to the GetWindow function is a bit problematic here, since changing the control's ID is going to break the JavaScript function.
This situation surely smells like it needs a good ol' Replace Magic Number with Symbolic Constant refactoring. I can achieve this by dynamically creating the Window control and using a constant for the value of the control's ID:
AnotherPage.aspx:
Window windowTest = new Window();
windowTest.ID = Consts.ID_WINDOW_TEST;
form1.Controls.Add(windowTest);
MasterPage.Master:
function MyFunc(){
var win = GetWindow("<%= My.Namespace.Consts.ID_WINDOW_TEST %>")
}
My question now is: How do you handle such situations? Do you create all your controls dynamically (like shown in the example above) when running into this situation, and are there any drawbacks using this approach, e.g. Designer doesn't display the control anymore? Or do you say "Screw it, nobody's going to change that control's ID" and leave it hard-coded in your code? Or do you have other approaches to this situation?
I personally am a fan of the of the first option (refactoring), since a) it makes sure that a change to the ID is not going to break my code and b) I almost never work with the Designer, but I thought I'd ask this question on SO to get some valuable opinions on this.
Thanks in advance for all the responses.
Greetings,
Giu
Update / Clarification:
I made a small error in the first version of this question by stating that the code snippets are placed in the same file. Since both the control and the JavaScript method are located in the same file, there is no need to create the control dynamically and defining the control's ID using a constant; by defining the control directly in the .aspx file I could use its ID in the JavaScript method as follows: GetWindow("<%= windowTest.ID %>");
But, my problem is another one; the control and the JavaScript method are each placed in different files, in which case the mentioned approach of using the control's ID doesn't work anymore. Therefore I introduced the solution mentioned in my question with the constant and the dynamic creation of the control. I now corrected both the filenames in my question so that the correct scenario is described to which my question is related.
In 4.0 you can control the client ID that's generated in master/content page situations quite well. but i believe if someone changes the ID manually in the page at one place and not in the javascript code it will still be a problem. If you are the only one who'll be working on this code then you can always be mindful and refactor properly. Otherwise you can go in for the constants option or store the IDs in a separate resource file.
In my opionion there a two suitable solutions:
1) Use the JQuery framework to get ahold of the html element you want to adress via JavaScript. JQuery is designed to be able to work with autogenerated hierarchically created control IDs
2) Use .net Framework 4.0 and don't use autogeneration of the Control ID. (I've heard that this is a new feature in 4.0. I think in your situation it might be worth trying out)
Check out Rick Strahl's blog post entitled "A generic way to find ASP.NET ClientIDs with jQuery"... it seems to have some good ideas that could be of some help to you.
He uses jQuery, as the first responder suggested, but does it in a way that you are using ASP.NET's built-in ClientID property to get the actual id ASP.NET generates and uses a client-side friendly mechanism that enables you to write script code referencing controls that won't break with ID changes.
I am creating a custom Attribute (extending System.Attribute). I know I can put it on another class easily enough by doing the following.
[MattsAttribute]
public class SomeClassWhichIsACodeBehind {
However, I need to be able to test this attribute easily, and putting it in the code-behind would cause a lot of extra effort to get it deployed to an environment which would respond to the behavior of attribute.
What I would like to do: declaratively apply this attribute to the .aspx page itself (which is really just another class that inherits from the code-behind). Is this possible? If so, what is the proper syntax for doing this?
Check out this post from ScottGu:
http://weblogs.asp.net/scottgu/archive/2005/08/02/421405.aspx
You'll have to extend Page, but it looks about the closest you can come to doing what you want without putting something in a CodeBehind.
I generally prefer to add controls dynamically, like table and generic html controls, to the ASPX page, rather than add them in the ASPX page and set the properties dynamically.
Which approach is considered "better practice"?
Also is using generic html controls dynamically a better practice than outputting formatted html strings to an asp:literal?
Keep them in the .aspx
Adding them dynamically leads to view state issues and they must be added in each post pack. I ran into this when building a user generated forms app. I Broke down and used the controls visibility property as a work around. That said if your eliminating view state and post back from your app these may not be issues for you.
https://web.archive.org/web/20211031102347/https://aspnet.4guysfromrolla.com/articles/092904-1.aspx
Since in both approaches you end up with a set of code that adds controls and assigns values to their properties then the best practice is the approach that is the most readable.
Due to complex decision logic it may be better to do it all yourself on the hand for fairly static control layout where only the properties need modifying placing the control in the ASPX would be more straight-forward.
In ASP.NET, is it possible to use both code behind and inline on the same page? I want to add some inline code that's related to the UI of the page, the reason to make it inline is to make it easy to modify as it outputs some HTML which is why I don't want to add it in the code behind, is this possible in ASP.NET?
Edit: I'm sorry, obviously my question wasn't very clear, what I meant is using a script block with runat="server", this is what I meant by inline code.
Thanks
Yes, you can use inline code just like in classic asp. You can use 'this' or 'me' to get to the code behind fields, methods, etc.
Yes, that will work, make sure the code behind class is declared as a partial class, which is the default these days anyway. Don't think it would work in 1 or 1.1