Get page author in CQ5 - aem

Is there any way to get the current page author's email address and other profile details in CQ5 ?
I need to publish it on my page. I could make it a text-component and let the author himself add it, but it would be cool to display it from backend ..
For now, I could only get the name using Page.LastModifiedBy()

You can get the author's username through the jcr:createdBy property on the page's jcr:content node.
You can then look up email addresses through the UserManager, which you can adaptTo from a JcrSession object. This page has some additional information on loading user information.
From a JSP you could do something like this:
<%#page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8" import="org.apache.jackrabbit.api.security.user.*, com.day.cq.commons.jcr.*" %>
...
<%
String createdBy = properties.get(JcrConstants.JCR_CREATED_BY, String.class);
UserManager userManager = resourceResolver.adaptTo(UserManager.class);
Authorizable authorizable = userManager.getAuthorizable(createdBy);
if (authorizable.hasProperty("profile/familyName")) {
String familyName = authorizable.getProperty("profile/familyName")[0].getString();
}
%>

Related

The foreach tag in JSP and how to write the code in the Java controller

I have one controller (RegisteredController.java) , and I want that the output of the controller is displayed in the JSP (its name is commment_form.jsp). So I use a forEach tag in the jsp to display a list of comments (the comments which the user has inserted about a given resource). For "resource" I usually mean an image. So there are a list of comments about an "image" and I want that all the comments are all displayed in the bottom page, when a comment is going to be inserted into the comment form. My question is how must be written the code into the controller in order to set the output for the jsp ? Should I use a #ModelAttribute , a put-attribute or something else ? Here is the code of the controller and of the jsp :
The comment_form.jsp is:
<form:form modelAttribute="comments">
<table class="commento">
<tr>
<th/>
<th>ID</th>
<th>Contenuto</th>
</tr>
<c:forEach items = "${comments}" var="comment">
<tr>
<td><c:out value="${comments.content}"></c:out></td>
<td><c:out value="${comments.content}</c:out></td>
</c:forEach>
</table>
</form:form>
The RegisteredController.java is:
#RequestMapping("/comment.do")
public String comment(#ModelAttribute Comment comment, BindingResult
bindingResult, Model model, Locale locale) {
User user=userService.getUserCurrent();
comment.setDatePubblication(SQLUtility.getCurrentDate());
comment.setIdUser(user.getId());
commentService.create(comment);
Object[] args = { comment.getId() };
String message = messageSource.getMessage("message.update", args,locale);
List<Comment> comments =
commentService.findAllCommentByResource(comment.getIdResource());
model.addAttribute("comments", comments);
model.addAttribute("id",comment.getIdResource());
model.addAttribute("message", message);
model.addAttribute("comment", comment);
return "redirect:/registered/comment_start.do";
}
Please any help ? I will appreciate . Thanks you.
In case of redirect pass additional data as redirect attributes.
To carry data across a redirect use RedirectAttributes#addFlashAttribute(key, value).
What Java doc says:
A RedirectAttributes model is empty when the method is called and is never used unless the method returns a redirect view name or a RedirectView.
After the redirect, flash attributes are automatically added to the model of the controller that serves the target URL.
Read more...
One extra note :
In JSP it should be ${comment.content} instead of ${comments.content}

Grails forms & URL mapping

I am writing a Grails app where I would like to setup a form that allows a user to type in an image ID number and this value will be passed to a controller / action that retrieves the image from S3 for the given image ID.
The desired url would be of the format example.com/results/1234. I have setup the following URL mappings:
class UrlMappings {
static mappings = {
"/$controller/$action?/$id?"{
constraints {
// apply constraints here
}
}
"/results/$id?" {
controller = "s3Image"
action = "getS3Image"
}
"/"(view:"/index")
"500"(view:'/error')
}
}
The following is how I have setup a form:
<g:form controller="results" method="get">
<input type="text" name="id" class="input-xxlarge" placeholder="http://www.example.com">
<button class="btn btn-inverse">Submit</button>
</g:form>
However this seems to submit the form to example.com/results?id=12345.
How would I alter my form or mappings such that I can produce the desired url after form submission?
Thanks!
<g:form controller="results" method="get">
will generate an HTML form whose action URL is /results (the reverse URL mapping for a controller named "results" with no action or id). When this form is submitted, the browser will add ?id=1234 to the end of this URL because the form method is GET. This is not something you can influence in your URL mappings on the server side.
Instead, you should have your form POST to a different controller action that redirects to the getS3Image action. The redirect will have access to the ID on the server side, so can generate the friendly-looking URL for the redirect.
UrlMappings:
"/results/$id?" {
controller = "s3Image"
action = "getS3Image"
}
"/findImage" {
controller = "s3Image"
action = "find"
}
S3ImageController:
def find() {
redirect(action:"getS3Image", id:params.id)
}
def getS3Image() {
// as before
}
GSP:
<g:form controller="s3Image" action="find" method="post">
<input type="text" name="id" class="input-xxlarge" placeholder="http://www.example.com">
<button class="btn btn-inverse">Submit</button>
</g:form>
Derek,
what you are seeing is correct behaviour. For the GET request you have two things
URL of request
Parameters
Parameters are appended after urls using urlencode and separated by &, so, when you have form with URL http://mydomain.com/controller/action/, and in this form you have two fields: id, name, then, upon submission, they will be passed like this: http://mydomain.com/controller/action/?id=3&name=someName
URLMappings are mapping only URL part of it. So, in your example UrlMapping are matched only to /results/ and id is not passed.
But that is ok, since you can still access the id parameter in your controller, just do it like this (inside s3Image controller):
def getS3Image() {
def id = params.id
}
Try very simple change in UrlMapping:
"/results/$id?" {
controller = "s3Image"
action = "getS3Image"
id = $id
}
and then for sure you have the id accessible in the s3Image controller via:
def id = params.id
I think you have two problems here. First, UrlMappings rules are matched in order of appearance, from top to bottom. First rule that grails matches is "/$controller/$action?/$id?". Move your rule "/results/$id?" above and it should take precedence. - check comment below post.
Your second mistake is declaration of form. I think you've meant:
<g:form controller="s3Image" method="getS3Image">

Html.RenderPartial & Multiple controls with same id error

I have made myself a small user control for consuming a feed, the code for said user control looks like this
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<SyndicationFeed >" %>
<%foreach (var rss in ViewData.Model.Items)
{
Response.Write("<div id={0}><a href={1} target=\"_blank\" /> <strong>{2}</strong></div>",
rss.Links[0].Uri.OriginalString, rss.Title.Text, rss.Title.Text);
Response.Write("<div>" + rss.Summary.Text.Truncate(100) + "</div>")
}%>
The code for the RssController looks like this
public virtual ActionResult Index()
{
string feedUrl = #"http://wdfw.wa.gov/news/newsrss.php";
using (XmlReader reader = XmlReader.Create(feedUrl))
{
SyndicationFeed rss = SyndicationFeed.Load(reader);
return View(rss);
}
}
And I call it in Site.Master like so
<%Html.RenderPartial("Index", Model);%>
I've also tried
<%Html.RenderPartial("Index", ViewData.Model);%>
All resulting in this this error:
Multiple controls with the same ID
'ctl00' were found. Trace requires
that controls have unique IDs.
Can someone help me figure out where I'm going wrong please :)
Can you try to use Html.RenderAction("Index","Rss") instead Html.RederPartial? When Html.RenderAction is called by ViewEngine, all code in your Index action is executed and Model with rss data goes to Index view to be generated to markup. And why do you use Response.Write, in view you can put html tags and this markup will be inserted where you are calling Html.RenderAction. Hope it will be helpful for you, if not, sorry, at least I've tried ))
Best regards,
Dima.

Behavior while passing objects inside objects in asp.net mvc?

I am sure everyone has come across this but I thought will ask this anyways. So here is what I have -
public class ABC
{
public int x;
public int y;
public XYZ obj;
}
public class XYZ
{
int x1;
int y1;
}
public ActionResult Test1()
{
ABC model= new ABC();
model.x=1;
model.y=2;
ABC.obj= new XYZ();
model.x1=12;
obj.y2=34;
return View(model);
}
[HttpPost]
public ActionResult Test1(ABC model)
{
//does not get XYZ obj
}
View-
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<Models.ABC>" %>
<% using (Html.BeginForm())
{%>
//stuff here
<%:Html.HiddenFor(model => model.obj)%>
<%}%>
If I do the hidden fields for explicitly for XYZ's fields x1 and y1 then I get back those values. Like this -
<%:Html.Hidden("Model.obj.x1",Model.obj.x1)%>
I guess this is expected behavior but am I missing anything here ?
Well, for one thing, your "inherits" attribute is wrong. Instead of
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="Models.ABC" %>
It should be
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<Models.ABC>" %>
If you want to use Models.ABC as your model. For another, the action methods you posted aren't even compilable, so it's difficult to tell what the real problem might be.
Sending composite objects like this works just fine for me, so there is most likely an issue with your implementation.
Update
Values for any persisted model properties have to be POSTed back from the editor page, which means they need to be stored in form fields. If the page generator isn't creating fields for those values (and I'm not sure it should - it would make more sense to me to include a partial view for nested objects), you'll need to add fields that are either editable or hidden.

ASP.NET MVC 2.0: How to read querystring value

I am trying to build a small ASP.NET MVC 2 application.I have a controller class with the below method in it
public ActionResult Index()
{
TestMvc.Models.PersonalInformation objPerson = new TestMvc.Models.PersonalInformation();
objPerson.FirstName = "Shyju";
objPerson.LastName = "K";
objPerson.EmailId="shyju#company.com";
return View(objPerson);
}
And when the page (View) being called, i can see this data there as my view has these data's displaying. Now i want to know how can i pass a query string in the url and use that id to build the PersonalInformation object.Hoe can i read the querystring value ? Where to read ?
I want the quesrtstring to be like
http://www.sitename/user/4234 where 4234 is the user id
http://www.sitename/user/4234 is not a querystring. The querystring is the part of the URL that comes after the ?, as in http://www.sitename/user?userId=42
However, the default routes that come with the MVC project template should allow you to simply change the signature of your action method to
public ActionResult Index(int id)
and you should get the desired result. You should look into how routing works in MVC if you want full control of your URLs.
Also, note that the index action is usually used for showing a list of all objects, so you probably want the Details action for showing 1 user object.
What you want is to modify your action to accept an id like so:
public ActionResult Index(string id)
{
TestMvc.Models.PersonalInformation objPerson = new TestMvc.Models.PersonalInformation();
if (!string.isNullOrEmpty(id))
{
objPerson = getPerson(id);
}
return View(objPerson);
}
Then add a route to your global.asax:
routes.MapRoute(
"MyRoute", // Route name
"user/{id}", // URL with parameters
new { controller = "mycontroller", action = "index", id = ""} // Parameter defaults
);