Render view in MVC for SEO in Umbraco - seo

I am trying to render a view for seo tags in umbraco cms. However I am not sure how it can be done. Is there some source I can look up to?

Tags for SEO and social media could be combined, as they share some of the same information.
On my umbraco installation I have added the following properties to website root node, page nodes and member nodes:
On top node:
siteName - textbox
siteDescription - textarea
siteLocale - textbox (ie. nb_NO)
facebookPageUrl- textbox
facebookAppId - textbox
twitterUserName - textbox
siteLogo - media picker
On pages
pageTitle - textbox
pageSnippet - textbox with 160 chars about the page content
author - member picker
On members
facebookProfilePage - textbox
twitterUserName - textbox
memberProfileUrl - textbox
Then i use the following code to render head meta tags on all pages:
#inherits Umbraco.Web.Macros.PartialViewMacroPage
#{
// SITE INFORMATION
string site_locale = "en_US";
if (Model.Content.AncestorOrSelf(1).HasProperty("siteLocale") && (Model.Content.GetPropertyValue<string>("siteLocale") != ""))
{ site_locale = Model.Content.GetPropertyValue<string>("siteLocale"); };
// Check if root node has defined site name, otherwise use domain name.
string domain = System.Web.HttpContext.Current.Request.Url.Scheme + "://" + System.Web.HttpContext.Current.Request.Url.Authority;
string site_name = Model.Content.AncestorOrSelf(1).HasProperty("siteName") ? Model.Content.AncestorOrSelf(1).GetPropertyValue("siteName").ToString() : HttpContext.Current.Request.Url.Host.ToString();
// Check if site description exist, and default text if not.
string site_description = Model.Content.AncestorOrSelf(1).HasProperty("siteDescription") ? Model.Content.AncestorOrSelf(1).GetPropertyValue("siteDescription").ToString() : "The website " + HttpContext.Current.Request.Url.Host.ToString();
string site_logo_url = "";
string site_logo_height = "";
string site_logo_width = "";
if (Model.Content.AncestorOrSelf(1).HasProperty("siteLogo") && (Model.Content.AncestorOrSelf(1).GetPropertyValue<int>("siteLogo") != 0))
{
var logo = Umbraco.TypedMedia(Model.Content.AncestorOrSelf(1).GetPropertyValue("siteLogo").ToString());
site_logo_url = domain + logo.Url;
site_logo_height = logo.GetPropertyValue<string>("umbracoHeight");
site_logo_width = logo.GetPropertyValue<string>("umbracoWidth");
}
string site_fb_app_id = Model.Content.AncestorOrSelf(1).GetPropertyValue("facebookAppId").ToString();
string site_fb_page_url = Model.Content.AncestorOrSelf(1).GetPropertyValue("facebookPageUrl").ToString();
string site_twitter_username = Model.Content.AncestorOrSelf(1).GetPropertyValue("twitterUserName").ToString();
// PAGE INFORMATION
// Use page title if defined, otherwise Model.Content.Name
string page_url = Model.Content.Url;
string page_title = Model.Content.HasProperty("pageTitle") ? Model.Content.GetPropertyValue("pageTitle").ToString() : Model.Content.Name.ToString();
DateTime page_created_date = Model.Content.CreateDate;
DateTime page_updated_date = Model.Content.UpdateDate;
string page_description = Model.Content.HasProperty("pageSnippet") ? Model.Content.GetPropertyValue("pageSnippet").ToString() : "";
// AUTHOR INFORMATION
// Check for information about the author of this page
bool hasAuthorInfo = false;
if (Model.Content.HasProperty("author") && (Model.Content.GetPropertyValue("author").ToString() != ""))
{
hasAuthorInfo = true;
}
string author_name = "";
string author_facebook_page = "";
string author_twitter_username = "";
string author_member_profile_url = "";
if (hasAuthorInfo)
{
var author = Members.GetById((int)Model.Content.GetPropertyValue("author"));
author_name = author.Name;
author_facebook_page = author.GetPropertyValue("facebookProfilePage").ToString();
author_twitter_username = author.GetPropertyValue("twitterUserName").ToString();
author_member_profile_url = author.GetPropertyValue("memberProfileUrl").ToString();
}
// FEATURED IMAGE
// Check if there is a featured image for this page
bool hasFeaturedImage = false;
string page_featuredimage_url = "";
if (Model.Content.HasProperty("featuredImage") && (Model.Content.GetPropertyValue<int>("featuredImage") != 0))
{
hasFeaturedImage = true;
}
if (hasFeaturedImage)
{
var image = Umbraco.TypedMedia(Model.Content.GetPropertyValue("featuredImage").ToString());
page_featuredimage_url = domain + image.GetCropUrl("1200x630"); // Preferred size by Facebook
}
}
<meta name="description" content="#page_description" />
<meta property="og:title" content="#page_title" />
<meta property="og:site_name" content="#site_name" />
<meta property="og:url" content="#page_url" />
<meta property="og:description" content="#page_description" />
<meta property="og:image" content="#page_featuredimage_url" />
<meta property="fb:app_id" content="#site_fb_app_id" />
<meta property="og:type" content="article" />
<meta property="og:locale" content="nb_NO" />
<meta property="article:author" content="#author_facebook_page" />
<meta property="article:publisher" content="#site_fb_page_url" />
<meta name="twitter:title" content="#page_title" />
<meta name="twitter:description" content="#page_description" />
<meta name="twitter:image:src" content="#page_featuredimage_url" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site" content="#site_twitter_username" />
<meta name="twitter:creator" content="#author_twitter_username" />
<script type="application/ld+json">
{
"##context": "http://schema.org",
"##type": "NewsArticle",
"mainEntityOfPage":{
"##type":"WebPage",
"##id":"#page_url"
},
"headline": "#page_title",
"image": {
"##type": "ImageObject",
"url": "#page_featuredimage_url",
"height": 630,
"width": 1200
},
"datePublished": "#page_created_date.ToString("o")",
"dateModified": "#page_updated_date.ToString("o")",
"author": {
"##type": "Person",
"name": "#author_name"
},
"publisher": {
"##type": "Organization",
"name": "#site_name",
"logo": {
"##type": "ImageObject",
"url": "#site_logo_url",
"width": "#site_logo_width",
"height": "#site_logo_height"
}
},
"description": "#page_description"
}
</script>

Related

Getting data from another page using XMLHttpRequest

Good morning everyone. I tried creating a site that could get information from another page and feed the response into a div tag, but it didnt work. I checked with a very similar one i learnt from. Here is the HTML code.
<html>
<head>
<script>
function checkit(){
var samxml; var username;
if (window.XMLHttpRequest){
samxml = new XMLHttpRequest();}
else {
samxml = new ActiveXObject("Microsoft.XMLHTTP");
}
samxml.onreadystatechange = function() {
if (samxml.readyState == 4 && samxml.status == 200){
document.getElementById("check").innerHTML = samxml.responseText;}
}
username = document.getElementById("username").value;
samxml.open("POST", "check.php",true);
samxml.send( "username" );
}
}
</script>
</head>
<body>
<form>
<label for ="username">User ID:</label>
<input type = "text" name = "username" id = "username"/>
<div id = "check"></div>
<button type = "button" onclick = "checkit()">Check</button>
</form>
</body>
</html>
Here is the PHP page:
//php file
<?php
$user = $_POST["username"];
if ($user == "samuel") {
echo "Hmm. Chosen! Choose another one";}
else {
echo "Nice one";}
?>
Thanks so much.

How to include changeset data of defect in AppSDK 1.32?

Could you please give me an example how to query the information?
We have the example to query defect in the way as below,
var queryConf = { type: 'defect',
key : 'defects',
fetch: true
};
Per Web Services API documentation Artifact object has Changesets collection on it. Defects inherit from Artifacts. Here is an example that builds a table of defects by priority with associated Changesets data:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!-- Copyright (c) 2010 Rally Software Development Corp. All rights reserved -->
<html>
<head>
<title>Defects By Priority with associated Changesets Example</title>
<meta name="Name" content="App Example: Defects by Priority and associated Changesets" />
<meta name="Version" content="2010.4" />
<meta name="Vendor" content="Nick M Rally lab" />
<script type="text/javascript" src="https://rally1.rallydev.com/apps/1.33/sdk.js?apiVersion=1.43"></script>
<script type="text/javascript">
var table;
var rallyDataSource = null;
function showTable(results) {
if(table) {
table.destroy();
}
for (var i=0; i < results.defects.length; i++) {
if(results.defects[i].Changesets.length > 0){
results.defects[i].ChangesetsMessages = "";
console.log(results.defects[i].Changesets.length);
for (var j=0; j < results.defects[i].Changesets.length; j++) {
results.defects[i].ChangesetsMessages += results.defects[i].Changesets[j].Revision;
results.defects[i].ChangesetsMessages += ' ';
results.defects[i].ChangesetsMessages += results.defects[i].Changesets[j].Message;
results.defects[i].ChangesetsMessages += '<br />';
}
}
}
var config = {
columnKeys : ['FormattedID', 'Name', 'Priority','ChangesetsMessages'],
columnHeaders : ['Formatted ID', 'Name', 'Priority','Changesets - Revision, Message'],
columnWidths : ['150px','150px', '150px', '300px'],
};
table = new rally.sdk.ui.Table(config);
table.addRows(results.defects);
table.display("defects");
}
function onSelectionChanged(sender, eventArgs) {
var queryObject = {
key : 'defects',
type : 'defect',
query: '(Priority = "' + eventArgs.value + '")',
fetch: 'Name,FormattedID,Priority,Changesets,Changeset,ObjectID,Message,Revision'
};
rallyDataSource.findAll(queryObject, showTable);
}
function onLoad() {
rallyDataSource = new rally.sdk.data.RallyDataSource('1111','2222','false','false');
var dpConfig = {
type : "defect",
attribute: "priority",
defaultDisplayedValue: "Low",
label: "Defect Priority:",
showLabel: true
};
var dpDropdown = new rally.sdk.ui.AttributeDropdown(dpConfig, rallyDataSource);
dpDropdown.display("priorityDiv", onSelectionChanged);
}
rally.addOnLoad(onLoad);
</script>
</head>
<body>
<div id="priorityDiv"></div><div id="defects"></div>
</body>
</html>

change operation of the controler

My default action code:
public ViewResult Act(int? id)
{
if (id == null)
ViewData["p"] = GetDefaultView();
else
ViewData["p"] = GetEditView((int)id);
return View("Index");
}
My Index view code:
<!DOCTYPE html><html><head></head><body>
<div id="content">#Html.Raw(ViewData["p"])</div></body></html>
How it is possible to use instead of ViewData a string ? How I can update #content only by means of $.ajax?
Before being able to use the $.ajax function you will first need to render a view which includes the jquery.js script:
<!DOCTYPE html>
#{ Layout = null; }
<html>
<head>
</head>
<body>
<div id="content"></div>
<!-- TODO: Adjust your proper jquery version here: -->
<script type="text/javascript" src="~/scripts/jquery.js"></script>
<script type="text/javascript">
$.ajax({
url: '#Url.Action("act")',
data: { id: 123 },
success: function(result) {
$('#content').html(result);
}
});
</script>
</body>
</html>
then you should adapt your Act controller action so that it returns some partial view or a Content result:
public ActionResult Act(int? id)
{
if (id == null)
{
return Content("<div>id was null</div>");
}
return Content("<div>id value is " + id.Value.ToString() + "</div>");
}
If you want to return a string, you could change your controller to return a ContentResult.
public ContentResult Act(int? id)
{
string html = "";
if (id == null)
html = GetDefaultView();
else
html = GetEditView((int)id);
var content = new ContentResult();
content.Content = html;
return content;
}

Multiple Bing Map Pushpins from SQL not showing in Firefox & Chrome but do in IE

I'm displaying a Bing Map (v7) in my Webmatrix2 website with a series of pushpins & infoboxes drawn from a SQL Express database using a JSON enquiry.
While the maps appears in all 3 browsers I'm testing (IE, FF & Chrome) the pushpins are sometimes not showing in FF & Chrome, particularly if I refresh with Cntrl+F5
This is my first JSON and Bing Maps app so expect there's a few mistakes.
Any suggestions on how to improve the code and get display consistency?
#{
Layout = "~/_MapLayout.cshtml";
}
<script type="text/javascript" src="~/Scripts/jquery-1.9.1.min.js"></script>
<script type="text/javascript" src="http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=7.0"></script>
<link rel="StyleSheet" href="infoboxStyles.css" type="text/css">
<script type="text/javascript">
var map = null;
var pinLayer, pinInfobox;
var mouseover;
var pushpinFrameHTML = '<div class="infobox"><a class="infobox_close" href="javascript:closeInfobox()"><img src="/Images/close2.jpg" /></a><div class="infobox_content">{content}</div></div><div class="infobox_pointer"><img src="images/pointer_shadow.png"></div>';
var pinLayer = new Microsoft.Maps.EntityCollection();
var infoboxLayer = new Microsoft.Maps.EntityCollection();
function getMap() {
map = new Microsoft.Maps.Map(document.getElementById('map'), {
credentials: "my-key",
zoom: 4,
center: new Microsoft.Maps.Location(-25, 135),
mapTypeId: Microsoft.Maps.MapTypeId.road
});
pinInfobox = new Microsoft.Maps.Infobox(new Microsoft.Maps.Location(0, 0), { visible: false });
AddData();
}
$(function AddData() {
$.getJSON('/ListSchools', function (data) {
var schools = data;
$.each(schools, function (index, school) {
for (var i = 0; i < schools.length; i++) {
var pinLocation = new Microsoft.Maps.Location(school.SchoolLat, school.SchoolLon);
var NewPin = new Microsoft.Maps.Pushpin(pinLocation);
NewPin.title = school.SchoolName;
NewPin.description = "-- Learn More --";
pinLayer.push(NewPin); //add pushpin to pinLayer
Microsoft.Maps.Events.addHandler(NewPin, 'mouseover', displayInfobox);
}
});
infoboxLayer.push(pinInfobox);
map.entities.push(pinLayer);
map.entities.push(infoboxLayer);
});
})
function displayInfobox(e) {
if (e.targetType == "pushpin") {
var pin = e.target;
var html = "<span class='infobox_title'>" + pin.title + "</span><br/>" + pin.description;
pinInfobox.setOptions({
visible: true,
offset: new Microsoft.Maps.Point(-33, 20),
htmlContent: pushpinFrameHTML.replace('{content}', html)
});
//set location of infobox
pinInfobox.setLocation(pin.getLocation());
}
}
function closeInfobox() {
pinInfobox.setOptions({ visible: false });
}
function getCurrentLocation() {
var geoLocationProvider = new Microsoft.Maps.GeoLocationProvider(map);
geoLocationProvider.getCurrentPosition();
}
</script>
<body onload="getMap();">
<div id="map" style="position:relative; width:800px; height:600px;"></div>
<div>
<input type="button" value="Find Nearest Schools" onclick="getCurrentLocation();" />
</div>
</body>
The JSON file is simply
#{
var db = Database.Open("StarterSite");
var sql = #"SELECT * FROM Schools WHERE SchoolLon != ' ' AND SchoolLon != 'null' ";
var data = db.Query(sql);
Json.Write(data, Response.Output);
}
Add your pinLayer, infobox, and infoboxLayer before calling the AddData function and see if that makes a difference. Also verify that school.SchoolLat and school.SchoolLon are numbers and not a string version of a number. If they are a string, then use parseFloat to turn them into a number. Other than that everything looks fine.

Struts2 + jQuery Autocompletion

I used the jQuery autocompletion for my Struts2 application.
Pratically, my action made a list of strings that jQuery use. This is the script:
$().ready(function() {
$("#tag").autocomplete("/myAction/Action", {
multiple : true,
autoFill : true,
minChars:1
});
});
During typing appear the box with the suggestions. The problem is that the box render another value,
exactly render the code of my JSP ( links to CSS for the autocomplete plug-in).
How can I solve this?
This is my JSP:
<html>
<head>
<script src="<%=request.getContextPath()%>/scripts/jquery-latest.js"></script>
<link rel="stylesheet" href="<%=request.getContextPath()%>/scripts/main.css" type="text/css" />
<link rel="stylesheet" href="<%=request.getContextPath()%>/scripts/jquery.autocomplete.css" type="text/css" />
<script type="text/javascript" src="<%=request.getContextPath()%>scripts/jquery.bgiframe.min.js"></script>
<script type="text/javascript" src="/<%=request.getContextPath()%>/query.dimensions.js"></script>
<script type="text/javascript" src="<%=request.getContextPath()%>/scripts/jquery.autocomplete.js"></script>
<script type="text/javascript">
$().ready(function() {
$("#tag").autocomplete("/myAction/Action", {
multiple : true,
autoFill : true,
minChars:1
});
});
</script>
</head>
<body>
<s:form action="Action" theme="simple">
<s:iterator value="elencoMateriali" var="asd">
<s:property value="#asd" escape="false"/>
</s:iterator>
<s:textfield id="tag" name="tagField" label="tag" />
</s:form>
</body>
I think it's too late for an answer, but the probles is still remaining in Struts2. I have made some modifications to solve such problem:
Copy the jquery.struts2.js file into you js path.
Edit the jquery.struts2.js fil and look for 'success: function(data)' in the handle of the Autocompleter Widget, and replace the function for the next one:
success: function(data) {
var x = 0;
if (data[o.list] !== null) {
var isMap = false;
if (!$.isArray(data[o.list])) {
isMap = true;
}
var result = [];
$.each(data[o.list], function(j, val) {
if (isMap) {
result.push({
label: val.replace(
new RegExp(
"(?![^&;]+;)(?!<[^<>]*)(" +
$.ui.autocomplete.escapeRegex(request.term) +
")(?![^<>]*>)(?![^&;]+;)", "gi"
), "<strong>$1</strong>" ),
value: val,
id: j
});
}
else {
if (o.listkey !== undefined && o.listvalue !== undefined) {
result.push({
label: val[o.listvalue].replace(
new RegExp(
"(?![^&;]+;)(?!<[^<>]*)(" +
$.ui.autocomplete.escapeRegex(request.term) +
")(?![^<>]*>)(?![^&;]+;)", "gi"
), "<strong>$1</strong>" ),
value: val[o.listvalue],
id: val[o.listkey]
});
}
else {
result.push({
label: data[o.list][x].replace(
new RegExp(
"(?![^&;]+;)(?!<[^<>]*)(" +
$.ui.autocomplete.escapeRegex(request.term) +
")(?![^<>]*>)(?![^&;]+;)", "gi"
), "<strong>$1</strong>" ),
value: data[o.list][x],
id: data[o.list][x]
});
}
}
x++;
});
response(result);
}
}
Now, if you subscribe a onSelectTopics method on your jsp code, you will have a new item.id element available, so you can set the id value into a hidden o whatever you want.
Now, your autocompleter show a list with the strong word, fills the input with the selection, and mantains the id in a variable you can catch.
Remember to add the modified js in the include header section.
<%# taglib prefix="s" uri="/struts-tags" %>
<%# taglib prefix="sx" uri="/struts-dojo-tags" %>
<s:form action="ActionJson" theme="simple">
<s:url id="elencoFuffa" action="ActionJSON"/>
<sx:autocompleter id="autocompleter" name="materiale" loadOnTextChange="true" preload="false" href="%{elencoFuffa}" size="24" loadMinimumCount="1" showDownArrow="false" cssClass="dropDown" onchange="submit();"/>
<s:submit value="Prosegui"/>
<s:property value="luoghiSmaltimento"/>
</s:form>
Now, the Action:
public class Action extends ActionSupport {
private String materiale;
private String luoghi;
private List<String> elencoMateriali;
private Map<String, String> json;
public String execute() throws Exception {
System.out.println("------------------" + materiale);
return SUCCESS;
}
public String getMateriali() throws Exception {
MaterialiDAO dao = new MaterialiDAO();
List<Materiali> toResult = new ArrayList<Materiali>();
toResult = dao.findAll();
elencoMateriali = new ArrayList<String>();
Iterator i = toResult.iterator();
while (i.hasNext()) {
Materiali m = (Materiali) i.next();
elencoMateriali.add(m.getValueNomemateriale());
}
return SUCCESS;
}
public String getJson() throws Exception {
json = new HashMap<String, String>();
if (materiale != null && materiale.length() > 0) {
MaterialiDAO dao = new MaterialiDAO();
List<Materiali> materiali = dao.findByLikeValue(materiale);
for (Materiali m : materiali) {
json.put(m.getValueNomemateriale(), "" + m.getIdMateriali());
}
}
return SUCCESS;
}
public String trovaLuogo() throws Exception {
LuoghismalDAO daoL = new LuoghismalDAO();
MaterialiDAO daoM = new MaterialiDAO();
Materiali m = daoM.findByMaterialiName(materiale);
if (m != null) {
luoghi = m.getLuoghismal().getValueDescrluogo();
return SUCCESS;
} else {
luoghi = "-- Scegliere un materiale --";
return SUCCESS;
}
}
/* Getters and setters */
At the end the struts.xml
<action name="ActionJSON" class="it.action.Action"
method="getJson">
<result type="json">
<param name="root">json</param>
</result>
</action>