I have a single Umbraco 7 instance that has 2 root nodes. One node points to stage.sctflash.com and the other node points to stage.bullydog.com. When I navigate to http://stage.bullydog.com/Products/accessories/podmount, the Request.Url.Host is stage.bullydog.com. Now, if I open up another tab and go to http://stage.sctflash.com/Products/accessories/podmount, the Request.Url.Host might be stage.sctflash.com, but sometimes, it just changes to stage.sctflash.com.
The one strange thing I noticed is that if I view the accessories node in Umbraco, I noticed the parent of it is stage.bullydog.com no matter if I am on stage.sctflash.com or stage.bullydog.com
I am using Request.Url.Host to determine as a query parameter to a database. I am basically getting the brand like this:
if(Request.Url.Host == "stage.sctflash.com")
return "sct";
else
return bullydog";
So essentially if Request.Url.Host is intermittently wrong, I get the wrong query parameter.
To see this in action, if you go to http://stage.sctflash.com/Products/accessories/podmount, you will see an SCT logo, then go to http://stage.bullydog.com/Products/accessories/podmount and you will see a Bully Dog logo. These logos are driven by Request.Url.Host. If you refresh http://stage.sctflash.com/Products/accessories/podmount, you most likely will see the Bully Dog logo now because Request.Url.Host is now stage.bullydog.com instead of stage.sctflash.com
This is the action method that is called when I go to this page: http://stage.sctflash.com/Products/accessories/podmount
public ActionResult GetAccessoriesByType(RenderModel model, string id)
{
string brand = Common.GetProductBrand(Request.Url.Host);
var productSearchResultsModel = new ProductSearchResultsModel
{
Accessories = _accessoryRepository.GetAccessoriesByType(id, brand)
};
return View("~/Views/accessories.cshtml", productSearchResultsModel);
}
Related
I came across a strange problem in my project today: I use this action throughout my website to generate breadcrumbs for a given page:
#Html.Action("BreadcrumbsWithHeader2", "SharedElements", new { pageName = #Model.pageName, department = #Model.department, menuHeading = #Model.menuHeading, id = "EandTHeader" })
Where it just returns a PartialView. This works great on every page except for one, where it began throwing this error:
No route in the route table matches the supplied values.
I've checked for things like spelling errors, etc., but am not sure how to debug this any further. What could cause something in the route table to go missing?
Edit: I've just noticed that any and all ActionLinks on the website pointing to this page (not the #Html.Action shown above, but rather the view where I call this partial) are producing blank href tags. The controller for it (if this helps) is here:
[Route("JobFair/FindAJobFair/{area}")]
public ActionResult FindAJobFair(string area, string sideMenu)
{
ViewBag.sideMenu = sideMenu;
JobFairsViewModel jobFairInfo = new JobFairsViewModel()
{
department = "Foo",
menuHeading = null,
pageName = "Job Fairs"
};
return View(jobFairInfo);
}
This route is typical of what I use elsewhere on the site (attribute routing).
Do you always provide a value for sideMenu? If you don't that may cause your problem. Try to modify your controller like this:
[Route("JobFair/FindAJobFair/{area}")]
public ActionResult FindAJobFair(string area, string sideMenu = null/*default value*/)
{
ViewBag.sideMenu = sideMenu;
JobFairsViewModel jobFairInfo = new JobFairsViewModel()
{
department = "Foo",
menuHeading = null,
pageName = "Job Fairs"
};
return View(jobFairInfo);
}
Hopefully this answer helps someone in the future - the problem had to do with my variable name area that was passed into the controller. Since my project has an 'Areas' folder it was causing an issue with routing. I simply needed to change area to something like region and the issue was solved.
I have a custom controller to send message. So I need to get the value of property field name and alias = "email", this will be used to send the email to.
this code below works
var id = umbraco.uQuery.GetNodeByUrl("/contact-us");
IPublishedContent root = Umbraco.TypedContent(id.Id);
return root.GetProperty("email", true).Value.ToString();
However the problem here is if the page name changes, the url will change and the code will break.
So how can I change the code above to get the current page id and insert it here (???);?
I think the code should be something like this:
IPublishedContent root = Umbraco.TypedContent(???);
return root.GetProperty("email", true).Value.ToString();
Any help will be apprecciated
Your solution will bring a problem if you have more than 1 'ContactUs' node, or none. Then you don't know which one is going to be get.
(Actually it's the first one found in the node tree, but then someone can change the order of them...)
Is your controller a Surface controller? You can just do this:
IPublishedContent currentNode = Umbraco.TypedContent(CurrentPage.Id)
Ok, I found the solution for my question.
var nodes = umbraco.uQuery.GetNodesByType("ContactUs");
if (nodes.Any())
{
IPublishedContent node = Umbraco.TypedContent(nodes.First().Id);
return node.GetProperty(property, true).Value.ToString();
}
Hope this will help somebody with the same problem.
When using:
#Model.AncestorOrSelf(3)
In a .cshtml template in Umbraco, this would presumably limit the node traversal to 3 levels. Is this correct, and if so can anyone also confirm if the current node has the index zero?
#Model.AncestorOrSelf(3)
Model.Content is the current page that we're on. AncestorsOrSelf is all
of the ancestors this page has in the tree. (level) means: go up to
level 1/2/3/... and stop looking for more ancestors when you get
there.
Above is the comment that you get with Umbraco 7.x rc version.
Take an example of the content tree below that is kind of similar to that you normally see in contents section in umbraco admin area:
Each content document has a level and by default it starts with 1.
In a .cshtml template in Umbraco, this would presumably limit the node
traversal to 3 levels
As you can see in the example below, the level gets on increasing - level + 1. so, it starts by 1 and then just go on adding 1 to your sub levels.
- Content
-- Home (level = 1)
-- About Us (level = 2)
-- Contact Us (level = 2)
-- News Area (level = 2)
-- News Item 1 (level = 3)
-- News Item 2 (level = 3)
-- Other Node (level = 1)
So when you mention 3 as parameter for AncestorOrSelf, you are asking to move to 3rd level in the tree from the current element that can be any document/partial view and stop looking for any more ancestors when its found.
AncestorOrSelf(level) returns a single item which if of type DynamicPublishContent i.e. you will have access to many properties like id, name, url, etc.
#CurrentPage.AncestorOrSelf(1)
// based on content structure above, the above statement will give you an item - Home.
It is basically for fetching ancestors by level, doesn't matter what your current level or currentpage object is.
For example, if you want to create a navigation in your main layout so as to share it on all pages of your site, you will do something like this in your template:
<ul>
#foreach(var page in #CurrentPage.AncestorOrSelf(1).Children)
{
<li>#page.Name</li>
}
</ul>
Based on our example, it will give you:
About Us, Contact Us, News Area (in list form and with proper links)
Adding to the answer from SiddharthP I think the OP is possibly looking for the #CurrentPage.Up(int) method - this is traverses up the tree from the current level by the specified amount of levels.
So if you want the grandfather of the current node - #CurrentPage.Up(2) or #Model.Content.Up(2) for the strongly typed version.
Think of it as Ancestor starts from the root of the content tree down and Up starts from where you are going towards the root.
I think the confusing bit is you use the CurrentPage object but start traversing from the top root node towards the CurrentPage. When we think of our Ancestors in humanity we don't start from the beginning of time!
If my understanding of the code is correct, .AncestorOrSelf(int) returns the ancestor (or self) of a node at the given level in the argument.
Taken from lines 948 & 956 of https://github.com/umbraco/Umbraco-CMS/blob/6.2.0/src/umbraco.MacroEngines/RazorDynamicNode/DynamicNode.cs
public DynamicNode AncestorOrSelf(int level)
{
return AncestorOrSelf(node => node.Level == level);
}
public DynamicNode AncestorOrSelf(Func<DynamicNode, bool> func)
{
if (func(this)) return this;
var content = this;
while (content.Level > 1) // while we have a parent, consider the parent
{
// see note in .Parent - strange things can happen
var parent = content.Parent;
if (parent == content) return null;
content = parent;
if (func(content))
return content;
}
return null;
}
Hope I've understood that correctly and that this helps.
i'm working on a symfony project to manage a database. First i explain how it works:
In the database, all elements are associated to an unique element 'scene'. When a user accesses the application, chooses what scene he wants to see (it saves that in a user parameter). So when listing elements, the application should only list elements associated with the scene selected by the user.
*Note: all elements have an scene attribute in the table definition.
So my problem comes here:
I developed a listing of an element entities using the help of a sfPropelPager class to paginate. Also added some filters to search in the list, and for that i used the filter system provided by symfony (<element>FormFilter.class.php and stuff).
Now i want the list to not show elements from other scenes than the selected by the user.
How can i do to add additional criteria to the criteria given by the filter class?
or How would you solve the problem?
here is my action code:
public function executeUnidadfilter(sfWebRequest $request){
$this->filter = new BaUnidadorganizativaTblFormFilter();
$c = $this->filter->getCriteria();
$this->filter->bind($request->getParameter($this->filter->getName()));
if($this->filter->isValid()){
$this->pager = new sfPropelPager('BaUnidadorganizativaTbl',$this->sfPropelPagerLines);
echo $this->getUser()->getEscenario();
$this->pager->setCriteria($c);
$this->pager->init();
}else{
$this->pager = new sfPropelPager('BaUnidadorganizativaTbl',$this->sfPropelPagerLines);
$this->pager->init();
}
$this->setTemplate('Unidadlist');
}
*Note: 'scene' mentioned below is Escenario in the code
thank you very much for your time
I solved the problem. The trouble was that i assigned the formfilter generated criteria to my criteria var Before the filter was filled. That's why of the error.
The resulting code is that:
public function executeUnidadfilter(sfWebRequest $request){
$this->filter = new BaUnidadorganizativaTblFormFilter();
$this->filter->bind($request->getParameter($this->filter->getName()));
if($this->filter->isValid()){
$this->pager = new sfPropelPager('BaUnidadorganizativaTbl',$this->sfPropelPagerLines);
$esc = $this->getUser()->getEscenario();
$c = new Criteria();
$c = $this->filter->getCriteria();
$c->addAnd('codigo_escenario',$esc);
$this->pager->setCriteria($c);
$this->pager->init();
}else{
$this->pager = new sfPropelPager('BaUnidadorganizativaTbl',$this->sfPropelPagerLines);
$this->pager->setCriteria($this->filter->getCriteria());
$this->pager->init();
}
$this->message=null;
$this->messageType=null;
$this->setTemplate('Unidadlist');
}
edit #2: Question solved halfways. Look below
As a follow-up question, does anyone know of a non-intrusive way to solve what i'm trying to do below (namely, linking objects to each other without triggering infinite loops)?
I try to create a asp.net-mvc web application, and get a StackOverFlowException. A controller triggers the following command:
public ActionResult ShowCountry(int id)
{
Country country = _gameService.GetCountry(id);
return View(country);
}
The GameService handles it like this (WithCountryId is an extension):
public Country GetCountry(int id)
{
return _gameRepository.GetCountries().WithCountryId(id).SingleOrDefault();
}
The GameRepository handles it like this:
public IQueryable<Country> GetCountries()
{
var countries = from c in _db.Countries
select new Country
{
Id = c.Id,
Name = c.Name,
ShortDescription = c.ShortDescription,
FlagImage = c.FlagImage,
Game = GetGames().Where(g => g.Id == c.GameId).SingleOrDefault(),
SubRegion = GetSubRegions().Where(sr => sr.Id == c.SubRegionId).SingleOrDefault(),
};
return countries;
}
The GetGames() method causes the StackOverflowException:
public IQueryable<Game> GetGames()
{
var games = from g in _db.Games
select new Game
{
Id = g.Id,
Name = g.Name
};
return games;
}
My Business objects are different from the linq2sql classes, that's why I fill them with a select new.
An unhandled exception of type 'System.StackOverflowException' occurred in mscorlib.dll
edit #1: I have found the culprit, it's the following method, it triggers the GetCountries() method which in return triggers the GetSubRegions() again, ad nauseam:
public IQueryable<SubRegion> GetSubRegions()
{
return from sr in _db.SubRegions
select new SubRegion
{
Id = sr.Id,
Name = sr.Name,
ShortDescription = sr.ShortDescription,
Game = GetGames().Where(g => g.Id == sr.GameId).SingleOrDefault(),
Region = GetRegions().Where(r => r.Id == sr.RegionId).SingleOrDefault(),
Countries = new LazyList<Country>(GetCountries().Where(c => c.SubRegion.Id == sr.Id))
};
}
Might have to think of something else here :) That's what happens when you think in an OO mindset because of too much coffee
Hai! I think your models are recursively calling a method unintentionally, which results in the stack overflow. Like, for instance, your Subregion object is trying to get Country objects, which in turn have to get Subregions.
Anyhow, it always helps to check the stack in a StackOverflow exception. If you see a property being accessed over and over, its most likely because you're doing something like this:
public object MyProperty { set { MyProperty = value; }}
Its easier to spot situations like yours, where method A calls method B which calls method A, because you can see the same methods showing up two or more times in the call stack.
The problem might be this: countries have subregions and subregions have countries. I don't know how you implement the lazy list, but that might keep calling GetCountries and then GetSubRegions and so on. To find that out, I would launch the debugger en set breakpoints on the GetCountries and GetSubRegions method headers.
I tried similar patterns with LinqToSql, but it's hard to make bidirectional navigation work without affecting the performance to much. That's one of the reasons I'm using NHibernate right now.
To answer your edited question, namely: "linking objects to each other without triggering infinite loops":
Assuming you've got some sort of relation where both sides need to know about the other... get hold of all the relevant entities in both sides, then link them together, rather than trying to make the fetch of one side automatically fetch the other. Or just make one side fetch the other, and then fix up the remaining one. So in your case, the options would be:
Option 1:
Fetch all countries (leaving Subregions blank)
Fetch all Subregions (leaving Countries blank)
For each Subregion, look through the list of Countries and add the Subregion to the Country and the Country to the Subregion
Option 2:
Fetch all countries (leaving Subregions blank)
Fetch all Subregions, setting Subregion.Countries via the countries list fetched above
For each subregion, go through all its countries and add it to that country
(Or reverse country and subregion)
They're basically equialent answers, it just changes when you do some of the linking.