I created a new module for my user dashboard in the content area. It works exactly as expected. However, I have some users who are locked into content nodes further down the tree and therefore can't see the main content root. When they first login, the new dashboard loads fine, but once they dig into the nodes, it disappears with no way to get back.
What options do I have for making this appear as a tab in the root node of the content they have visible? I tried the user control wrapper but was getting a bunch of errors.
Unfortunately, the only way I have found to accomplish this is to use the 'umbraco usercontrol wrapper'. I was able to get my code working out of the box with it by inherting from:
System.Web.UI.UserControl, umbraco.editorControls.userControlGrapper.IUsercontrolDataEditor
I also added the following to my main class based on an example I found:
public string umbracoValue;
public object value
{
get
{
return umbracoValue;
}
set
{
umbracoValue = value.ToString();
}
}
Those were the only modifications I had to make and it started to function as expected.
Related
I have a grails application that takes user input (create page/method), the user then clicks a Save button (save method that executes service) and then the results are displayed (list method) on a page, for example http://localhost:8080/myApp/myclass/save.
The users would like each results run to be saved to a unique URL so they can share it, bookmark it, save it later, whatever. I have NO idea how to go about this and google searches turn up little to nothing.
For example an application run would result in the data being displayed at http://localhost:8080/myApp/myclass/systemname/datetimestring/someuniquedata/
Is this even possible? Any pointers GREATLY appreciated.
EDIT
Here is my urlMappings contents.
class UrlMappings {
static mappings = {
"/$controller/$action?/$id?"{
constraints {
// apply constraints here
}
}
"/" {
controller = "api"
action = "create"
}
"500"(view:'/error')
}
}
When I display the results it's done through the list method shown here.
def list(Integer max) {
List<Api> api = Api.findAllBySessionId(session.id, [sort:'dateCreated'])
api = api[-2..-1]
[apiInstanceList: api, apiInstanceTotal: api.size()]
}
So I have the unique session ID. How do I need to modify "mappings"?
Every domain object that you're saving will have an autogenerated ID (assuming you're using GORM, which is definitely likely). It sounds like all you're asking for is a /show/id page where you can access a particular object via ID.
A url mapping for "/$controller/$action?/$id?" is a pretty straightfoward way to handle this, and is provided by default (and used by scaffolded controllers also).
If you'd rather not use an autogenerated ID (maybe you're moving objects from one database to another, or updating the ID for some reason?) you can consider using java.util.UUID.randomUUID() to generate a random, unique identifier and save that as a field on your object. You could then use .findByUuid with the input parameter.
I added a default MvcApplication (MVC 4) (its name is MvcApplication3 matching the name of my solution's) width Home views (About, Index, Contact) and that will be my startup (bold in VS solution explorer's interface) project. Then I added another project (MvcApplication, but this time an empty one) called MvcApplication2 to the solution. Then I added the latter project as a reference to the first. I also added a controller called TestController (green line) to the referenced project and generated a view for its Index (red arrow) method. However, when I go to a link /Test or /Test/Index, the view I am expecting (red arrow) is not shown. Then I added the same folder Test with Index.cshtml (blue arrow) to the main project and now I am seeing its contents rather than the project's where my controller sits in.
Is it possible to make the application look for the views in the other project rather than the startup one?
I am adding the image of the structure to make it easier to follow.
P.S.: probably related: the breakpoint IS being hit in the Index method of TestController.
tldr; blue view is used instead of a red one
I think your problema is that you have set MvcApplication3 as startup Project and is causing you to open the view off that Project.
Is it possible to make the application look for the views in the other
project rather than the startup one?
Yes its posible, you can redirect your application the url. Think this your application have a url http://localhost:(someport) you can set redirect to the port of the second application.
I put a link to for better understanding a routing system of MVC: Documentation of routing system
As far as I know, you can't link to projects together like that. Each project becomes its own website with its own address. The reason you might put multiple projects together in one solution is to share things like classes, services, etc. I think what you're needing is areas:
http://www.codeproject.com/Articles/714356/Areas-in-ASP-NET-MVC
With some ideas from me and a friend of mine and a link about overriding RazorViewEngine I finally got what I wanted working exactly how I was expecting it to:
I created a folder named ViewsBase in the main project.
I rewrote RazorViewEngine this way: I only changed the place that was needed for me, leaving everything else like I found in the constructor of RazorViewEngine:
public class MyCustomViewEngine : RazorViewEngine
{
public MyCustomViewEngine()
{
...
ViewLocationFormats = new[]
{
"~/Views/{1}/{0}.cshtml",
"~/Views/{1}/{0}.vbhtml",
"~/Views/Shared/{0}.cshtml",
"~/Views/Shared/{0}.vbhtml",
"~/ViewsBase/{1}/{0}.cshtml",
"~/ViewsBase/{1}/{0}.vbhtml"
};
...
(I find it rather disturbing how I am unable to format the code properly. Can someone give me a hand please?)
and in Global.asax of the main project I added:
ViewEngines.Engines.Clear();
var ourViewEngine = new
ViewEngines.Engines.Add(ourViewEngine);
AreaRegistration.RegisterAllAreas();
...
I added a post-build event command:
xcopy /s "$(ProjectDir)Views\*.*" /Y "$(SolutionDir)$(SolutionName)\ViewsBase\"
It started looking for the views in the expected order
I added a ViewStart file to the base project to make it render the Layout too.
I am growing increasingly frustrated with Umbraco. I've been working on an Umbraco project for a little while now and I have been unable to figure out how to solve my problem (one of many).
Scenario - I have a content managed page and on this page users can search for things (these things come from an entirely different database to Umbraco). This is fine, I've created a child action which loads the form for search and created the controller method which returns the results. However, each result I need to link to another content managed page (the same content managed page for each result) that takes an ID so I can inject some dynamic data into the content managed page.
Great, I've got a method for handling this request in my surface controller and I can create an Html.ActionLink for each result that when clicked hits my controller action with the id parameter.
Problem - When each link is clicked the url that gets hit is
http://localhost:5645/umbraco/surface/{controllername}/{actionname}/?id={id}
However this request is outside the Umbraco context, so when I try to return any page with the following controller code, I get the following error:
[ActionName("ShowDetials")]
public ActionResult GetProperty(int propertyId)
{
return View("~/Views/TestView.cshtml");
}
Cannot render a macro when UmbracoContext.PageId is null.
So my initial thoughts were to have a separate controller which inherits from Umbraco.Web.Mvc.RenderMvcController and try to handle the request in there, but then this raises other issues like being unable to use #Html.ActionLink to link to a RenderMvcController, I also don't want to have two controllers to handle content from the same section.
The other issues I have is passing custom models to the view.
If anyone can help me, I would be eternally grateful.
For any developer having this same issue the only way I have been able to solve it is by having two controllers. A surface controller to handle the initial rendering of the search form and page and to display the results of the search, then a separate rendermvccontroller to handle clicking on an individual result and displaying a 'details' page.
However, this in my opinion isn't great and I would still greatly appreciate it if anyone has another solution.
We are beginning the process of moving from Web Forms to MVC for all of our new applications. I am working on porting our Master Page over and am trying to satisfy the requirements that we need a single master page to be used by all applications. The primary navigation for the application needs to be in a menu within the master page. Accomplishing this was easy, the hard part is that each application may need to determine what to display in the menu using a unique set of rules. Some apps can simply say, here's the menu structure to use via something like a SiteMap. Others need to determine what is displayed in the menu based on what roles the user has, this can also be handled easily with a SiteMap. The situation that I'm struggling with is that some apps need to generate the menus based on the roles the user has, but also on the data on which they are working. i.e. The same user may have different option in the menu for a page if they are working on object 'foo' than they do if working on object 'bar'.
What I've done at this point, is I've created an HtmlHelper that is called by the master page view and takes a list of objects of a custom type and returns an unordered list that is styled by a jQuery plugin to display the menu. The list of objects the helper method takes are passed to the view using the ViewData dictionary. Currently, the value of this ViewData node is set within the constructor of each controller. This allows each page, and potentially each method, to set a different menu without having to set the value in each action method, unless its needed. I have also created a class that parses a SiteMap and returns the list of items needed to build the menu. This class is what I'm using to set the ViewData value in the controller. The idea being that if an application needed more control of how the menu data was generated, they could create their own class to generate the data as long as it returns a list of the correct type of objects.
This solution seems to work fine so far, it just doesn't 'feel' right for some reason. I'm hoping that I can either get some ideas of better way to do this or some reassurance that this is a valid approach to solving this problem.
If it is something that will be on every page, do something like this:
Create a base controller:
public class MyBaseController : Controller
Have this controller get the data it needs and send that data in the ViewData["menu"] to the View. Then have all your controllers inherit from this one:
public class HomeController : MyBaseController
In the Master Page, loop through your ViewData and create your menu.
(I did something like this for my sub-menu which displayed a list of categories.)
In the book I am reading (Pro ASP.NET MVC Framework by Apress) they use Html.RenderAction for the menu in the masterpage. I am a Asp.net MVC novice so maybe somebody else can give more info about this.
You can download the sourcecode at apress.com though so maybe that could help.
In the Wicket Application class I have mounted a page at the location /about
mountBookmarkablePage("about", AboutPage.class);
I verify that the about page is available at /about. Then in the page which needs a link to the about page, I use the Wicket Link class:
add(new Link("link") {
#Override
public void onClick() {
setResponsePage(AboutPage.class);
}
};
)
The links work as expected but the target URL diplayed in the browser status bar when the mouse is over the link looks like
http://localhost:8080/?wicket:interface=:0:linkpage:repeating:1:link::ILinkListener::
A workaround which I have found is to use ExternalLink
new ExternalLink("link", "/about", "about");
This changes the target URL to
http://localhost:8080/about
which is displayed in the browser status bar when the mouse is over the link.
Is there a way to use the mounted URL as the target link with Wicket Link class, or is there a way to get the mount location for a class, so that I can use it to build the link url for AboutPage.class (instead of hard coding it in the ExternalLink constructor)?
For this purpose you should use BookmarkablePageLink (as you're saying you're doing), to set the link label (or any other content for that matter) just call .add(Component... c) since BookmarkablePageLink is actually a MarkupContainer.
So, to create a link to AboutPage.class you need to do this:
BookmarkablePageLink aboutLink = new BookmarkablePageLink("link", AboutPage.class);
aboutLink.add(new Label("linkText", "Go to About page"));
add(aboutLink);
and the matching markup
<a wicket:id="link"><span wicket:id="linkText">Link text goes here</span></a>
Yeppers, it's slightly more verbose but also very easily extensible. If you want to, you can create your own convenience subclass of BookmarkablePageLink called BookmarkableTextLink and have a
new BookmarkableTextLink(String id, Class<Page> pageClass, String linkText);
constructor for it.
Found a solution: the BookmarkablePageLink class
add(new BookmarkablePageLink("link", AboutPage.class));
This solution only has a small problem: the link label can not be set, maybe this can be done by assigning a model.