In the Kentico Documentation I only found the info as below...
Is there any way to access the properties value in the layout as show below? I tried to use macro but it didn't work.
I just want to display the properties value in my custom layout. Any methods other than access through the code? I'm using portal engine, I have no idea how to access the code behind...
The layout is ASCX, so you won't be able to use macros as per your example.
If you just need the value, you can use the GetValue method. There's also GetStringValue, if the type of your property is a string
<% GetStringValue("MyPropertiesValue1", string.Empty); %>
If you need to render the value, you will need to call Page.DataBind() and use a data binding expression. Your layout would look something like this:
<%# GetStringValue("MyPropertiesValue1", string.Empty) %>
<%# GetStringValue("MyPropertiesValue2", string.Empty) %>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
Page.DataBind();
}
</script>
None if this is really elegant, so you might want to reconsider your approach.
Related
Not sure how to label the title of this question. I have a snippet of re-usable content with a Subscribe Icon + Social Icons. This snippet is used in almost every page on the site through a repeater.
What I want to do is to attach the CurrentDocument.DocumentName to the Subscribe Icon in order to know which page people came from, something like this:
Subscribe However, looks like that doesn't work. This string shows in the address bar when click on the link: www.domain.com/subscribe?p={%%20CurrentDocument.DocumentNamePath%20|(user)|(hash)34ce5eaa55a6a6ad89...%} I figure because CurrentDocument is actually referring to the snippet itself, not the real current page displaying in the browser. Could you help?
Is your repeater transformation aspx? If so, use <%# %>, so <%# CurrentDocument.DocumentName %>
If this is an ASCX transformation it is like a web user control, so you can call C# methods, try this
<%# CMS.MacroEngine.MacroResolver.Resolve("{%CurrentDocument.DocumentName#%}")%>
Or you can do linke in this in ACSX transformation:
<script runat="server">
string test = "";
protected override void OnInit(EventArgs e)
{
test = CMS.MacroEngine.MacroResolver.Resolve("{%CurrentDocument.DocumentName#%}");
}
</script>
<h1><%# test%></h1>
Consult MacroResolver class for other methods
P.S. Sorry I didnt check my answer in Kenitco for the frist time. Just make sure you calling MacroResolver from the right name space.
I need to check for the presence of an anchor tag in the url, from within a transformation. I'm assuming that would be in the Page_Load function, but I can't seem to find any good documentation on this.
How can I go about it?
Thanks!
Anchors don't get passed to the server and therefore Uri.Fragment is not present in the Request object. You can use the property only to construct URIs.
If you need to pass data to the server, use query parameters or hidden fields.
If you need to evaluate URIs stored in the DB, use Brenden's approach.
Within your transformation you can create a simple function using some similar code below:
<script runat="server">
public bool UrlHasAnchor()
{
string myUrl = ValidationHelper.GetString(Eval("YourUrlColumn"), "");
if(myUrl.Contains("#"))
{
return true;
}
return false;
}
<script>
Now call it when you're setting your value like so:
<%# If(UrlHasAnchor(), "do something crazy", "don't do anything at all") %>
You can also create a custom transformation method too which would do the same thing.
Why is that the scriptPath variable is out of scope in the bottom of the code?
Shouldn't it be in scope throughout this page? In MVC, if I mark this on top of the page like
#{
string scriptPath = "assets/scripts/",
gkoConfig = "GkoConfig.js";
}
it is available throughout the current View. What am I missing now that I'm back to WebForms for a while?
If I change the code position, It get's weirder as inside the <head> I no longer have access to teh variable, but I do have, inside the <body> now... :-/
When you declare a variable in a Web Forms .aspx file, you’re actually declaring a local variable inside an auto-generated rendering method. ASP.NET generates separate rendering methods for all tags marked runat="server", so you actually get a separate method for your head element. Now, the variable you declare can only exist in one of these methods - hence the 'weird' behavior.
You can see how this works if you pre-compile your application using aspnet_compiler.exe. You will get compiled DLL files for each of your web forms pages; just open one of those up in Reflector to see the generated code. I wrote a minimal equivalent of your code with the variable declared outside the head tag, and here’s the top-level render method that I got:
private void __Render__control1(HtmlTextWriter __w, Control parameterContainer)
{
string str = "scripts/";
__w.Write("\r\n<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\r\n\r\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\r\n");
parameterContainer.Controls[0].RenderControl(__w);
__w.Write("\r\n<body>\r\n ");
parameterContainer.Controls[1].RenderControl(__w);
__w.Write("\r\n <script type=\"text/javascript\" src=\"");
__w.Write(str);
__w.Write("jquery-1.4.1.min.js\"></script>\r\n</body>\r\n</html>\r\n");
}
You see that the variable that I declared (here named str) is scoped to this method, and it's calling other methods to render the head (and a form element marked runat="server".)
A quick and dirty solution might be to simply remove the runat="server" from your head tag; however, I’d recommend that you declare a protected variable in your code-behind class for this. Adding a line like this to your code-behind file would work:
protected string scriptPath, gkoConfig;
You can then use these variables anywhere in your Web Forms code.
You could also declare your constants like this:
<script runat="server">
private const string scriptPath = "assets/scripts/";
private const string gkoConfig = "GkoConfig.js";
</script>
I suspect the head of the ASPX page gets processed separately from the body.
This problem is easily solved - all you need to do is use a class field in the code-behind with the access level set to protected.
we are trying to build a more loosely coupled composite based web application, and looking at various options and frameworks.
The idea is like when the user browse to a page, the uri will be resolved on the server for a resource and a list of actions to take based on the configuration.
The view will be composed by some html markups and some components that are based on other URIs for their contents. The components are reusable and should not have any ideas about each other (maybe the context).
this is just an idea, and wanna see how the OpenRasta framework would help on this. I might be completely wrong with the approach; maybe this can be easily done with current asp.net webform and mvc framework, but i would like to see your opinion.
I have just completed an OpenRasta site that relies on standard webcontrols that I inject into my views, passing on the strongly typed Resource (supplied by OR via the handler) to enable the control to surface resource properties etc in the usual way.
The resource instance carries the path to the control to be loaded and injected (Resource.ControlPath). This is set in the handler by concatenating aspects of the URI to find the control. This allows different URIs to request different versions of the same control that live at different locations in the site file hierarchy.
So, for example, ClientA requires an intro view with lots of client-specific text and features. ClientB also requires an intro page with different content and features.
This give two URIs
/myapp/clienta/intro
/myapp/clientb/intro
Configuration
ResourceSpace.Has.ResourcesOfType<IntroResource>()
.AtUri("/myapp/{client}/intro")
.HandledBy<IntroHandler>()
.RenderedByAspx("~/Views/IntroView.aspx");
IntroHandler.cs
public class IntroHandler
{
public OperationResult Get(string client)
{
var controlPath = ClientService.GetIntroControlPath(client);
if (controlPath.IsEmpty()) return new OperationResult.NotFound();
return new OperationResult.OK{
ResponseResource = new IntroResource{
ControlPath = controlPath,
Client=client
}
};
}
}
}
Intro.aspx
<%# Page Language="C#" Inherits="OpenRasta.Codecs.WebForms.ResourceView<xx.IntroResource>" MasterPageFile="~/Views/View.Master" %>
<asp:Content ContentPlaceHolderID="head" ID="head" runat="server">
<link href="/assets/CSS/intro.css" rel="stylesheet" type="text/css" />
<%
var userControl = Page.LoadControl(Resource.ControlPath) as UserControl;
if (userControl == null) return;
var property = userControl.GetType().GetProperty("Resource");
if (property == null) return;
property.SetValue(userControl, Resource, null);
IntroContentControlHolder.Controls.Add(userControl);
%>
</asp:Content>
<asp:Content ContentPlaceHolderID="body" ID="content" runat="server">
<asp:placeholder runat="server" id="IntroContentControlHolder"></asp:placeholder>
</asp:Content>
Intro.ascx
<%# Control CodeBehind="intro.ascx.cs" Language="C#" Inherits="xxxx.intro"%>
<h1>Welcome <%=Resource.Client%></h1>
...Lots more UI stuff
Intro.ascx.cs
public class intro : UserControl
{
public IntroResource Resource { get; set; }
}
Therefore each version of the intro control extends the View with client specific features.
I make security system in mvc application. In MVC it must be done by AuthorizeAttribute and roles string via actions methods.
Could i make this stuff: instead of action resolve I want to make view where html parts are hidden depend on current user permission set (For example: save button are not visible if user not Administrator).
Within your views, you can do conditional checks, such as:
<% if (User.IsInRole("Admin")) { %>
An Admin-only link
<% } %>
In partial views, the User property is not exposed, but you can still do it:
<% var user = HttpContext.Current.User; %>
<% if (user.IsInRole("Admin")) { %>
An Admin-only link
<% } %>
Brian - i don't think this is a good idea to 'hide' the admin parts. you basically then just expose to logic to anyone opening the html in 'view source' mode. it would be better to have an admin view and a 'normal' view and just do a case statement in the contoller action to deliver the appropriate view where required (still not the best option, but far better than hiding fields). better still, have a master view that contains partialviews which are only rendered if it's the correct user type etc..
just my 'view' on the topic..
jim
You can do either A or B
a) Create partial views for the various elements that change and do something like
<% if (HttpContext.Current.User.IsInRole("Administrator"))
{
Html.RenderPartial("AdminStuff");
}
else
{
Html.RenderPartial("RegularStuff");
}
%>
b) Set the role in your viewdata/viewmodel and use it in the code (not recommended as the view should really contain no logic)
In the controller
ViewData["Admin"] = HttpContext.Current.User.IsInRole("Administrator");
In the view
<% if ((bool)ViewData["Admin"]) { %>
<!-- Show admin stuff -->
<% } %>
Thanks to all for your answers. I see that view dynamic render is a bad practic in mvc applications. I'm used to think that there can be some libraries or templates.
BTW When i told to my PM that a string with roles is a common pattern he sad "Hard code!!!!". Now I'm designing some WCF service with will be an "Aplication Authoriser" ))).
Everyone here seems to forget that there is css for such stuff. You can do the thing you want very easily, at least I am doing at already, and it's working flawlessly.
Let me give you a simple example
Make sure your operations buttons/regions have defined css classes
css class: MODULE-OPERATION
e.g.
Module User
Operations: Add, Edit, Delete, List
Add User
Whenever changing (adding/updating/deleting) roles, you generate a css file for each role
e.g.
You decide that only administrators can add users so this css is generated
//admin_css.css
.USER-ADD { display: none; }
Everytime the page is opened you check what role the user has, and based on the role, you load the css file in you header. So your gui correlates to the logic you have in your application without so much hassle.