I'm getting started with ASP.NET Boilerplate where I am using the free start-up template of ASP.NET Core Multi Page Web Application.
My question is regarding the left hand navigation bar. I have the NavigationProvider in my project where the abstract class is implemented. I have been testing out some of the properties available in the MenuItemDefinition, specifically the order and isVisible. My expectation was that I could set both the order and isVisible properties and that this would show in the application when running. I don't however see any of these properties actually being used to either set the order of the menu items or control their visibility.
For the order property I updated the Default.cshtml of the SideBarNav component to implement an OrderBy so I can get the correct order. This works but I'm not sure if this is the recommended approach.
Is it correct that setting the order when adding a MenuItemDefinition doesn't actually have any consequence to the running application and that this property is here with the expectation that I implement the behavior as I've done in the Default.cshtml?
My reason for wanting to control the order this way rather than by just the order the items are added is related to creating different modules that each have their own NavigationProviders.
Is it correct that setting the order when adding a MenuItemDefinition doesn't actually have any consequence to the running application and that this property is here with the expectation that I implement the behavior as I've done in the Default.cshtml?
Yes, the templates (as of v5.2.0) do not use nor implement ordering of user menu items.
I suggest implementing an extension method to easily change the ordering across the project.
public static IOrderedEnumerable<UserMenuItem> OrderByCustom(this IEnumerable<UserMenuItem> menuItems)
{
return menuItems
.OrderBy(menuItem => menuItem.Order)
.ThenBy(menuItem => menuItem.DisplayName);
}
Regarding versions: You are using v5.1.x and below. As of v5.2.0, the template has been migrated to use AdminLTE 3 instead of AdminBSB for the MVC UI, so the following changes are incompatible.
v5.2+
I have submitted a PR to implement the ordering: aspnetboilerplate/module-zero-core-template#510
var orderedMenuItems = Model.MainMenu.Items.Where(x => x.IsVisible).OrderByCustom().ToList();
var subMenus = Model.Items.Where(x => x.IsVisible).OrderByCustom().ToList();
Files changed:
Web.Mvc/Views/Shared/Components/SideBarMenu/Default.cshtml
Web.Mvc/Views/Shared/Components/SideBarMenu/_MenuItem.cshtml
v5.1.x and below
Note that you should change in 3 places (corresponding to 3 nesting levels) in Default.cshtml.
#foreach (var menuItem in Model.MainMenu.Items.OrderByCustom().ToList())
#foreach (var subMenuItem in menuItem.Items.OrderByCustom().ToList())
#foreach (var subSubMenuItem in subMenuItem.Items.OrderByCustom().ToList())
File changed:
Web.Mvc/Views/Shared/Components/SideBarNav/Default.cshtml
Related
I am trying to list the view template’s properties so we can compare them with another old template.
For example what model elements are hidden or have overrides in a given template or which Revit links have been hidden or overridden in a given template.
View Template
(https://www.google.com/search?q=view+template+revit&rlz=1C1GGRV_enUS770US770&source=lnms&tbm=isch&sa=X&ved=0ahUKEwjLndrd2cTbAhVESq0KHX1cAPwQ_AUICygC&biw=1536&bih=824#imgrc=Q0v-pV7Nxl4kfM:)
I’m looking to devise a View Template Compare tool and access to the owner and creator of them.
public void ApplyViewTemplateToActiveView()
{
Document doc = this.ActiveUIDocument.Document;
View viewTemplate = (from v in new FilteredElementCollector(doc)
.OfClass(typeof(View))
.Cast<View>()
where v.IsTemplate == true && v.Name == "MyViewTemplate"
select v)
.First();
using (Transaction t = new Transaction(doc,"Set View Template"))
{
t.Start();
doc.ActiveView.ViewTemplateId = viewTemplate.Id;
t.Commit();
}
}
With Revit API you can access with:
GetTemplateParameterIds Method / ViewTemplateId Property
The Revit API exposes almost all the ViewTemplate properties.
For instance this method returns all the Visibility/Graphic Overrides for a specific category:
https://apidocs.co/apps/revit/2019/ed267b82-56be-6e3b-0c6d-4de7df1ed312.htm
The only thing I couldn't get for a ViewTemplate are the "includes", but all the rest seems to be there.
Update:
The list or properties "not included" can be retrieved with GetNonControlledTemplateParameterIds().
Yes, and no.
Yes, I guess you can use Forge Model Derivative API to export RVT file and then build a dashboard around the View Templates data. That's assuming that View Templates data actually gets exported when the model is translated. That data is not attached to any geometry so I would not be surprised if it was skipped. The question here is why? This is like renting a 16-wheel truck to move a duffel bag across the street.
No, if your intention is to directly interact with the RVT model. Forge can view it, but to push anything back or request changes to the model, is not available yet. Then again, I am not even sure that the view template data is available via model derivative exports.
This brings me another alternative. Why not just collect the data using Revit API, the standard way and then push it out to a Database and build on top of that? There is no reason to employ Forge for any of that.
Thanks Jeremy, I had dig into your amazing website and also some solution that Konrad post in the Dynamo Forum about this. In Revit seems pretty achievable, you filter the View that is View Template and then extracts these properties, is it correct?.
I am wondering if someone can point me in the right direction with Forge.
Some amazing guys are developing a BQL https://www.retriever.works/.
BQL(Building Query Language) is a query language for buildings, similar to how SQL is a query language for databases. It is fast and flexible. BQL helps improve efficiency for QA/QC (quality assurance and quality control), and building data extraction without leaving Revit. I am also trying these and I would like to understand if there are some works where I could start with Forge next week about this.
Trying to migrate an existing solution away from the deprecated Microsoft.Xrm.Client namespace to just use the generated service context from CrmSvcUtil using CrmSDK 9.0.0.5.
Previously we were using Microsoft.Xrm.Client.CodeGeneration.CodeCustomization to get a lazily loaded context.
I have two copies of the same solution and have been working through some of the API changes.
I have enabled Proxy Types
client.OrganizationServiceProxy.EnableProxyTypes();
Which to my understanding switched it to act in a lazily-loaded manner. However, none of the navigation properties are loading as expected.
The few blog posts that I've found around this shift to CrmServiceClient etc suggest that even without lazy loading I should be able to load the property manually with a call to Entity.LoadProperty() which will either load the property or refresh the data. However, after doing that the navigation property is still null (specifically I'm trying to use a Contact navigation property). When I look through the RelatedEntities collection it is also empty.
I know that the entity has a related contact item as if I use a context generated with Microsoft.Xrm.Client.CodeGeneration.CodeCustomization it returns it and I can also see it in CRM itself using an advanced search.
var connectionUri = ConfigurationManager.ConnectionStrings["Xrm"].ConnectionString;
var client = new CrmServiceClient(connectionUri);
client.OrganizationServiceProxy.EnableProxyTypes();
var context = new XrmServiceContext(client);
var result = context.new_applicationSet.FirstOrDefault(x => x.new_applicantid.Id == CurrentUserId);
//result.Contact is null
context.LoadProperty(result, "Contact");
//result.Contact is still null
//result.RelatedEntities is empty
I'm building a Durandal SPA that may benefit from a cacheViews setting of true or false, depending on the individuals usage of the app.
This is how I currently have it set in shell.html:
<div class="page-host" data-bind="router: { cacheViews:true }"></div>
And in a child router like in samples/index.html:
<div>
<!--ko router: { cacheViews:false }--><!--/ko-->
</div>
1) Can these be changed at runtime? If so, how?. Does it matter that one is using data-bind and the other is using ko comment style?
2) How granular is this value? Is it per "router" or per "route"? As you can see, I have a parent router and a child router, so there are 2 places in my html code where I can set cacheViews. From my testing, it appears as if they are independent of each other. Can anyone confirm? Can I set this value on individual routes like /#page1, /#page2, /#samples/list, etc?
3) Because the page event life-cycle is different between true/false I need to have some specific logic in my vm depending on this value. How can I retrieve it for the current route?
Thanks
1) Can these be changed at runtime? If so, how?
With any knockout binding, the binding is recomputed if the bound value triggers subscriptions. That means cacheViews can be changed at runtime if it is an observable.
I'm not sure if the right way to do this is ko.observable({ cacheViews: false }) or { cacheViews: ko.observable(false) }. In fact, I believe which one will work is somewhat dependent on the version of knockout you're running, but one of them will work.
2) Does it matter that one is using data-bind and the other is using
ko comment style?
No.
3) How granular is this value? Is it per "router" or per "route"?
Per router. More specifically, per binding.
4) Can I set this value on individual routes like /#page1, /#page2,
/#samples/list, etc?
There's nothing out of the box that lets you set cacheViews per route. cacheViews is processed in the compose binding, which is being called under the hood in the router and so you would need to hook in there. However, Durandal is excellent about exposing hooks at every part of the lifecycle for custom logic. I'm sure with a little digging you can come up with your own customization to handle this.
5) Because the page event life-cycle is different between true/false I
need to have some specific logic in my vm depending on this value. How
can I retrieve it for the current route?
You would want to create the observable from (1) in your viewModel and have your associated view read it, like any other observable in knockout. Then, you will be able to access the current value directly off the viewModel. For example:
viewModel
viewModel = {
settings: ko.observable({
cacheViews: false
})
}
view
<!-- ko router: settings -->
So, I'm not quite sure how I should structure this in CakePHP to work correctly in the proper MVC form.
Let's, for argument sake, say I have the following data structure which are related in various ways:
Team
Task
Equipment
This is generally how sites are and is quite easy to structure and make in Cake. For example, I would have the a model, controller and view for each item set.
My problem (and I'm sure countless others have had it and already solved it) is that I have a level above the item sets. So, for example:
Department
Team
Task
Equipment
Department
Team
Task
Equipment
Department
Team
Task
Equipment
In my site, I need the ability for someone to view the site at an individual group level as well as move to view it all together (ie, ignore the groups).
So, I have models, views and controls for Depart, Team, Task and Equipment.
How do I structure my site so that from the Department view, someone can select a Department then move around the site to the different views for Team/Task/Equipment showing only those that belong to that particular Department.
In this same format, is there a way to also move around ignoring the department associations?
Hopefully the following example URLs clarifies anything that was unclear:
// View items while disregarding which group-set record they belong to
http://www.example.com/Team/action/id
http://www.example.com/Task/action/id
http://www.example.com/Equipment/action/id
http://www.example.com/Departments
// View items as if only those associated with the selected group-set record exist
http://www.example.com/Department/HR/Team/action/id
http://www.example.com/Department/HR/Task/action/id
http://www.example.com/Department/HR/Equipment/action/id
Can I get the controllers to function in this manner? Is there someone to read so I can figure this out?
Thanks to those that read all this :)
I think I know what you're trying to do. Correct me if I'm wrong:
I built a project manager for myself in which I wanted the URLs to be more logical, so instead of using something like
http://domain.com/project/milestones/add/MyProjectName I could use
http://domain.com/project/MyProjectName/milestones/add
I added a custom route to the end (!important) of my routes so that it catches anything that's not already a route and treats it as a "variable route".
Router::connect('/project/:project/:controller/:action/*', array(), array('project' => '[a-zA-Z0-9\-]+'));
Whatever route you put means that you can't already (or ever) have a controller by that name, for that reason I consider it a good practice to use a singular word instead of a plural. (I have a Projects Controller, so I use "project" to avoid conflicting with it.)
Now, to access the :project parameter anywhere in my app, I use this function in my AppController:
function __currentProject(){
// Finding the current Project's Info
if(isset($this->params['project'])){
App::import('Model', 'Project');
$projectNames = new Project;
$projectNames->contain();
$projectInfo = $projectNames->find('first', array('conditions' => array('Project.slug' => $this->params['project'])));
$project_id = $projectInfo['Project']['id'];
$this->set('project_name_for_layout', $projectInfo['Project']['name']);
return $project_id;
}
}
And I utilize it in my other controllers:
function overview(){
$this->layout = 'project';
// Getting currentProject id from App Controller
$project_id = parent::__currentProject();
// Finding out what time it is and performing queries based on time.
$nowStamp = time();
$nowDate = date('Y-m-d H:i:s' , $nowStamp);
$twoWeeksFromNow = $nowDate + 1209600;
$lateMilestones = $this->Project->Milestone->find('all', array('conditions'=>array('Milestone.project_id' => $project_id, 'Milestone.complete'=> 0, 'Milestone.duedate <'=> $nowDate)));
$this->set(compact('lateMilestones'));
$currentProject = $this->Project->find('all', array('conditions'=>array('Project.slug' => $this->params['project'])));
$this->set(compact('currentProject'));
}
For your project you can try using a route like this at the end of your routes.php file:
Router::connect('/:groupname/:controller/:action/*', array(), array('groupname' => '[a-zA-Z0-9\-]+'));
// Notice I removed "/project" from the beginning. If you put the :groupname first, as I've done in the last example, then you only have one option for these custom url routes.
Then modify the other code to your needs.
If this is a public site, you may want to consider using named variables. This will allow you to define the group on the URL still, but without additional functionality requirements.
http://example.com/team/group:hr
http://example.com/team/action/group:hr/other:var
It may require custom routes too... but it should do the job.
http://book.cakephp.org/view/541/Named-parameters
http://book.cakephp.org/view/542/Defining-Routes
SESSIONS
Since web is stateless, you will need to use sessions (or cookies). The question you will need to ask yourself is how to reflect the selection (or not) of a specific department. It could be as simple as putting a drop down selection in the upper right that reflects ALL, HR, Sales, etc. When the drop down changes, it will set (or clear) the Group session variable.
As for the functionality in the controllers, you just check for the Session. If it is there, you limit the data by the select group. So you would use the same URLs, but the controller or model would manage how the data gets displayed.
// for all functionality use:
http://www.example.com/Team/action/id
http://www.example.com/Task/action/id
http://www.example.com/Equipment/action/id
You don't change the URL to accommodate for the functionality. That would be like using a different URL for every USER wanting to see their ADDRESS, PHONE NUMBER, or BILLING INFO. Where USER would be the group and ADDRESS, PHONE NUMBER< and BILLING INFO would be the item sets.
WITHOUT SESSIONS
The other option would be to put the Group filter on each page. So for example on Team/index view you would have a group drop down to filter the data. It would accomplish the same thing without having to set and clear session variables.
The conclusion is and the key thing to remember is that the functionality does not change nor does the URLs. The only thing that changes is that you will be working with filtered data sets.
Does that make sense?
I'm developing a SL3 application with Prism. I need to have support for validation (both field level (on the setter of the bound property) and before save (form level)), including a validation summary, shown when the save button is pressed.
But the samples I can find googling are either SL3 with a lot of code in code behind (very uncool and un-Prismy), or WPF related.
Does anyone know a reference application with some actual validation I can look into?
Cheers,
Ali
There aren't any from Microsoft at present, but I'll pass this one onto the PRISM team tomorrow to see if we can get a basic Form Validation example inside the next rev of PRISM.
That being said, you can put a validator per Form that essentially validates each field (semantic and/or syntax validation) and should all pass, will return a true/false state.
A way I typically do this is I attach a "CanSave" method to my Commands ie:
SaveOrderCommand = new DelegateCommand<object>(this.Save, this.CanSave);
private bool CanSave(object arg)
{
return this.errors.Count == 0 && this.Quantity > 0;
}
Then in the this.CanSave, i then put either the basic validation inside this codebase, or I call a bunch of other validators depending on the context - some would be shared across all modules (ie IsEmailValid would be one Validator i place in my Infrastructure Module as a singleton and pass in my string, it would then true/false as a result). Once they all pass, ensure CanSave returns true. If they fail, the CanSave will return False.
Now if they fail and you want to trigger a friendly reminder to the user that its failed theres a number of techniques you can use here. I've typically flagged the said control at validation as being "failed".. (i wrote my own mind you, so up to you which toolkits you could use here - http://www.codeplex.com/SilverlightValidator is a not bad one).
Now, I typically like to do more with Forms that have validation on them by not only highlighting the said control (red box, icon etc) but also explain to the user in more detail whats required of them - thus custom approach is a solution I've opted for.
At the end of the day, you're going to have to do some of the heavy lifting to validate your particular form - but look into ways to re-use validators where they make sense (email, SSN etc are easy ones to re-use).
HTH?
Scott Barnes - Rich Platforms Product Manager - Microsoft.