I have a website which allows users to send messages to eachother. My layout on the top has a notification bar, which shows the number of unread messages. My table with messages has a property of Unread (true, false). I can easily search for unread messages for the current user, I just don't know how to send it to layout. Is there a controller I can use to send to a layout?
You can define that your layout pages use a model. I would recommend using an interface as model.
public interface IMessageNotification {
public int UnreadMessagesCount {get; set;}
}
All ViewModels that use the layout page have to implement this interface.
You can access it in the Layout.cshtml like this:
#model IMessageNotification
<div class="myNotification">#Model.UnreadMessagesCount</div>
See ASP.NET MVC Razor pass model to layout
Another way would be to define a section in the layout that acts as placeholder for the notification, and every view can render the notification how it wants.
Layout:
#* No model directive required *#
#if (IsSectionDefined("Notification")) {
#RenderSection("Notification")
}
Concrete View (SomeConcreteViewModel has property UnreadMessagesCount):
#model SomeConcreteViewModel
#section Notification {
<div class="myNotification">#Model.UnreadMessagesCount</div>
}
As for the controller: you can use a helper class that fills the required data into the IMessageNotification interface implemented by the viewmodels. Call this in every action that renders a view using this layout.
I created a partial view, and used a controller to call it. I queried the DB for unread messages, and sent the count via ViewBag. I call it with #Html.Action. Didn't know this gets rendered each time user refreshes a web page. Thank you all :)
Related
I am using ASP.NET Core 2.0 and Visual Studio 2017.
I want to create a Razor partial view to display the menu of our application. The menu is created dynamically as each user will only have menu items for which they have the necessary permissions (so the menu will be different for each user).
The problem I'm having is persisting the menu in the Razor partial view. There is no PageModel code-behind in a Razor partial view, so the problem I'm having is that the menu disappears when you click onto another page. I've persisted the menu in session storage, but I can't figure out how to load the menu from session storage into the Razor partial view.
I've tried loading the session storage menu into ViewData but this is wiped out when you click on another page.
How do I persist data in my Razor partial views?
Instead of using partial view, consider using a view component.
public class MenuComponent : ViewComponent
{
SomeDependency userDetails;
public MenuComponent(SomeDependency userDetails)
{
//store this userDetails data to extract profile info in Invoke method
this.userDetails = userDetails;
}
public IViewComponentResult Invoke()
{
//check for logged in user profile here and return appropriate view
return View(viewName,ModelObjectForView);
}
}
1.Create required menu views
Create the appropriate views for displaying menu for each role or use
conditional rendering.
Please note view for view components will be looked in to
/Views/ControllerName/Components/ViewComponentName/ViewName.cshtml this
location instead of /Views/ControllerName/ViewName.cshtml.
2.Define Layout Page
Now, since you need to display menu for all the pages user navigates to, you
need to extract this view component in a layout page. Create a _Layout.cshthml
file and make sure views that need to show menu item uses this layout page.
In the _Layout.cshtml , you can now render the view component defined above by calling
#await Component.InvokeAsync(nameof(MenuComponent))
3.Using ViewComponent instead of PartialView
I am suggesting use of ViewComponent over PartialView in this case because
ViewComponent will allow you to have its own model (RoleDetails for user in
your case) in comparison to PartialView
where you will have to pass some child data from view model and hence will have
to keep that data in each of your view model. Otherwise , you can even use PartialView. The important thing here is layout page that will help you keep menu across all views presented to user.
I copied an old form to a new site, old form is working but the new form is not, I don't know what's missing.
The old form is at : http://nmjava.com/gate/Contact_Information.html
New form is at : http://gatecybertech.com/Contact_Information.html
I know HTML, but don't know Angular.js, I know when a submit button is pressed, the action in the form is called, but in my case it looks like this:
<form name="form" id="form" Method="post" class="form-horizontal" ng-hide="submitDone == true" ng-submit="onSubmit(form.$valid)" novalidate="novalidate">
After I looked into the code on that page, I can't find where "onSubmit(form.$valid)" is happening, I guess there must be some function that handles it, but where is it ?
Angular is an MVC framework, A.K.A Model, View, Controller. The view in this case is the UI (HTML), the model contains the business logic, for example state management or AJAX calls,
and the controller reacts to the view in order to get data from the model, to send back to the view.
there can be many views, controllers and models.
Angular parses the html for ng-* directives (as well as other, custom directives) and attempts to traverse the controller's scope in order to evaluate the property's value, in this case onSubmit(form.$valid).
In order to find the correct controller that contains your function,
you should consider the following:
Angular controllers are attached to a view using the ng-controller directive. An HTML element containing this directive will have its scope point to the controller specified in that directive's property value (ng-controller="mainCtrl"), and all child elements will have access to that scope as well.
Angular has scope hierarchy, meaning your code can be in any of the nested controllers which are parent elements of your ng-submit.
Angular also has a global scope, dubbed $rootScope, which can be accessed from within any part of your view, as well as controllers if the $rootScope dependency is injected into them.
So, in short, your function is in in one of the controllers. Using the above points you can narrow down the scope (no pun intended) of your search to one of the relevant controllers, usually found in a controllers folder in your application.
I'm trying to develop an application using ASP.Net MVC 5 & Entity Framework 6.
I'm getting confused with Html helpers.
I have a Driver,Vehicle Entities. When i entering a new driver, there is a select box to select and assign a vehicle to the new driver.
All vehicle RegNo properties should be loaded to the #Html.DropDownListFor() when page loading. And when submitting the page, the ID of the selected vehicle should be inserted to the VehicleID column in Driver entity.
This is the UI of Driver view.
This is my Entity
user select the RegNo of the Vehicle in #Html.DropDownListFor() and the ID of the vehicleshoud be submitted to the Entity when submitting the form.
How to do this in runtime?
Thanks in advance.
You can always loop over your collection manually:
<select name="Something">
#foreach(var thing in Model.Something)
{
var selectedStr = someExpression ? "selected" : "";
<option #selectedStr value="#thing.SomeValue">#thing.SomeText</option>
}
</select>
It may even be worth it to examine the HTML produced by the HTML helper method so you can replicate it more exactly. It wouldn't be far off from this, the helper methods tend to generate pretty simple and straightforward markup.
As long as the resulting form element has the same name/values, there will be no difference between this and the HTML helper when posting the form.
I have the following situation. We are building a new intranet for our company and, being a charity, accomplishing AA accessibility is a must. I am a SharePoint developer and we are getting the design from a third party company. That said, designers made a custom design in a way that it is barely recalling SharePoint at all, like a kind of mixture between a completely different design like if it was a publishing site and at the same time, the idea is to work with as much out of the box functionality as possible.
That means that if I create a list, all the look and feel will be the customized one while the functionality must be kept. So I would get a settings page for the list whose functionality should be kept as is but the design should be the new design. A custom list (custom but created in SharePoint) would have a new, editing and display form which should be out of the box... but with the new design.
The problem comes with this out of the box forms. The design is using divs for displaying all the HTML controls that are linked to each of the columns of a custom list. Unfortunately, SharePoint 2013 out of the box list forms tabulate the fields using HTML tables.
Apparently there is a limit of 30000 characters in this post, so I can't paste the code from the out of the box form to show the tables, but what I did is to create a form with an example of each of the possible fields in SharePoint and then look at how many tables I was getting there. And I can't add a screenshot because I need 10 reputation...
I have removed in previous projects the tables in SharePoint webparts using a control adapter, which, by the way, I am using in this website too. But I am struggling with how I can change this HTML tables in the forms. I have tried to render the form same way that I did with the webpart zones but it is not working in a similar way.
Here you have the code for the Control Adapter for webpart zones:
public class WebpartControlAdapter : System.Web.UI.Adapters.ControlAdapter
{
protected override void Render(HtmlTextWriter writer)
{
var wpz = Control as Microsoft.SharePoint.WebPartPages.WebPartZone;
if (wpz != null)
{
WebPartCollection wpColl = new WebPartCollection(wpz.WebParts);
foreach (System.Web.UI.WebControls.WebParts.WebPart wp in wpColl)
{
wp.RenderControl(writer);
}
}
}
}
And here what I tried based on that, which is basically destroying my page completely:
public class PageControlAdapter : System.Web.UI.Adapters.PageAdapter
{
protected override void Render(HtmlTextWriter writer)
{
var currentPage = Control as Page;
if (currentPage != null)
{
System.Web.UI.HtmlControls.HtmlForm form = new System.Web.UI.HtmlControls.HtmlForm();
form = currentPage.Form;
form.RenderControl(writer);
}
}
}
So my question are if anyone has a solution or way to achieve this.
Thanks for any possible help.
P.D.: before you propose that, changing the .aspx files coming OOTB from SharePoint is not an option because we hold other web applications in the same farm and making changes there would provoke changes in all other websites.
I'am not sure what you want to acomplish.
If you are creating totally custom list and want a New, Display and Edit forms completly different then you can define which forms to use in contentType:
https://msdn.microsoft.com/en-us/library/office/aa543825.aspx
Example:
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<!-- Parent ContentType: Workflow Task (0x010801) -->
<ContentType ID="0x010100AF4E4BE6CF8048959C4172F4298CE42A"
Name="MyName"
Group="MyGroup"
Description="MyDescription"
Version="0">
<FieldRefs>
</FieldRefs>
<XmlDocuments>
<XmlDocument NamespaceURI ="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms/url">
<FormUrls xmlns="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms/url">
<New>_layouts/MyFolder/New.aspx</New>
<Display>_layouts/MyFolder/New.aspx</Display>
<Edit>_layouts/MyFolder/Edit.aspx</Edit>
</FormUrls>
</XmlDocument>
</XmlDocuments>
</ContentType>
</Elements>
In code behind you get current item:
SPListItem item = SPContext.Current.ListItem;
Other possibility is to add script editor webpart on NewFrom, DisplayForm and EditForm. In script use jquery to change look of fields.
To auto populate scriptEditorWebparts you can make eventhandler fired on ListAdded event
Example: We have an employee list page, that consists of filter criteria form and employee list grid. One of the criteria you can filter by is manager. If the user wants to pick a manager to filter by, he uses the lookup control and popup window is opened, that also has filter criteria and employee list grid.
Now the problem is, that if the popup window is not an iframe, some of the popup elements will have same names and ids as the owner page. Duplicate ids cause Kendo UI to break as by default MVC wrapper generates script tags with $("#id").kendoThingie.
I have used iframe in the past, but content that does not fit in iframe window like long dropdown lists gets cut off and now IE11 especially causes various issues like https://connect.microsoft.com/IE/feedback/details/802251/script70-permission-denied-error-when-trying-to-access-old-document-from-reloaded-iframe.
What would be the best solution here? Generate unique ids for all elements on Razor pages? Modify partial page content that is retrieved by Ajax making ids unique? Something else?
It sounds like you are using a partial page as the content to a Kendo window. If this is the case then just provide your partial with a prefix like so at the top of the page.
#{
ViewData.TemplateInfo.HtmlFieldPrefix = "MyPrefix"
}
Now when you create a kendo control via the MVC wrapper like so
#(Html.Kendo().DropDownListFor(o => o.SomeProperty)
.....
)
The name attribute will be generated as "MyPrefix.SomeProperty" and the id attribute will be generated as "MyPrefix_SomeProperty". When accessing it within Jquery I like a shorter variable name so I usually do
string Prefix = ViewData.TemplateInfo.HtmlFieldPrefix
After setting the prefix. Then use
var val = $('##(Prefix)_SomeProperty').data('kendoDropDownList').value();
Note after this change. If you are posting a form from that partial you will need to add the following attribute to your model parameter on the controller method like so. So that binding happens correctly.
[HttpPost]
public ActionResult MyPartialModal([Bind(Prefix = "MyPrefix")] ModeViewModel model) {
.....
}
Now with all of that said. As long as you keep your prefixes different for each partial your control ids and names will be unique. To ensure this I usually make my prefix name be the same as my cshtml page that I am creating. You would just need to worry about JS function names. Also, note when closing a kendo window all DOM still exist. You just hide it. If this causes you the same issue you just need to be sure to clear the DOM of the modal on close. Similar to how BurnsBA mentioned. Note because of this is the reason why I try to make sure I use the least amount of kendo windows as possible and just reuse them via the refresh function pointing to a different URL.
$('#my-window').data('kendoWindow').refresh({
url: someUrlString
, data: {
someId: '#Model.MyId'
}
}).open().center();
Then on the modal page itself. When posting I do the following assuming nothing complicated needs to happen when posting.
var form = $('#my-form'); //Probably want this to be unique. What I do is provide a GUID on the view model
$('#my-window').data('kendoWindow').refresh({
url: form.attr('action')
, data: form.serialize()
, type: 'POST'
}).open().center();
We do something similar, and have the same problem. We have create/edit/delete popups that fetch data via ajax. Different viewmodels might reference the same model on the same page, and if you open multiple popups (create item type 1, create item type 2) then the second and subsequent popups can be broken (kendo ui error such that a dropdown is now just a plain textbox). Our solution is to delete all dom entries when the popup is closed so there are no conflicts between ids in different popups. We use bootstrap, so it looks like
<script type="text/javascript">
$('body').on(
// hook close even on bootstrap popup
'hidden.bs.modal', '.modal',
function () {
$(this).removeData('bs.modal');
$(this).find('.modal-content').html(''); // clear dom in popup
});
</script>
Note that our popup has some outer html elements and identifiers, but the content is all in
<div class="modal-content"> ... </div>