umbraco - usercontrols - umbracoNaviHide - umbraco

I know I can get the current node with 'var top = Node.GetCurrent();' but I cant seem to find where I can get the related properties, specifically 'umbracoNaviHide'. I'd like to know how to access the same data that is accessible from XSLT in a user control

To get properties you need to use the GetProperty() method.
var top = Node.GetCurrent();
top.GetProperty("umbracoNaviHide").Value;

In Umbraco 8, you will have to do something like this:
private List<NavigationListItem> GetChildNavigationList(IPublishedContent page)
{
List<NavigationListItem> listItems = null;
var childPages = page.Children.Where(i => i.IsPublished());
if (childPages != null && childPages.Any() && childPages.Count() > 0)
{
listItems = new List<NavigationListItem>();
foreach (var childPage in childPages)
{
int myTrueFalseFieldValue = 1;
if (childPage.HasProperty("umbracoNaviHide"))
{
Int32.TryParse(childPage.GetProperty("umbracoNaviHide").GetValue().ToString(), out myTrueFalseFieldValue);
//myTrueFalseFieldValue = 0 // hide the page
//myTrueFalseFieldValue = 1 // don't hide the page
string name = childPage.Name;
int test = myTrueFalseFieldValue;
}
if (myTrueFalseFieldValue == 1)
{
NavigationListItem listItem = new NavigationListItem(new NavigationLink(childPage.Url, childPage.Name));
listItem.Items = GetChildNavigationList(childPage);
listItems.Add(listItem);
}
}
}
return listItems;
}
Above code will make sure that those pages which have set there umbrachoNaviHide checkbox property to true will not be included in the navigation list.
In order to see how to make custom property: umbracoNaviHide, please search youtube for "Day11: Hide Pages from Navigation in Umbraco"

Related

Is it good way to update data in ASP.NET MVC?

I am updating existing data in a database. Basically, I am retrieving all data from the table and one by one I am updating each column manually. Do you think it's a good way? Or please suggest me another short way to do the same. My method is looking so long I mean a lot of lines to update.
[HttpPost]
public ActionResult SaveMovie(HttpPostedFileBase file, MovieViewModel model)
{
if (!ModelState.IsValid)
{
var viewModel = new MovieViewModel
{
ProHouses = _context.ProHouses.ToList()
};
return View("AddMovie", viewModel);
}
if (model.Movies.Id == 0)
{
if (file != null)
{
Guid RandomName = Guid.NewGuid();
var fileExtention = Path.GetExtension(file.FileName);
var FileName = RandomName + fileExtention;
var path = Path.Combine(Server.MapPath("~/MovieTitle"), RandomName + fileExtention);
file.SaveAs(path);
model.Movies.TitleURL = FileName;
}
_context.Movies.Add(model.Movies);
}
else
{
var movieInTable = _context.Movies.SingleOrDefault(m => m.Id == model.Movies.Id);
movieInTable.Budget = model.Movies.Budget;
movieInTable.Writer = model.Movies.Writer;
movieInTable.Country = model.Movies.Country;
movieInTable.Genre = model.Movies.Genre;
movieInTable.Duration = model.Movies.Duration;
movieInTable.Plot = model.Movies.Plot;
movieInTable.Name = model.Movies.Name;
movieInTable.ProHouseId = model.Movies.ProHouseId;
movieInTable.Rating = model.Movies.Rating;
movieInTable.Director = model.Movies.Director;
movieInTable.Year = model.Movies.Year;
movieInTable.TitleURL = model.Movies.TitleURL;
}
_context.SaveChanges();
ViewBag.Message = "Movie Added";
return View("Confirmation");
}
I am confused about this part:
else
{
var movieInTable = _context.Movies.SingleOrDefault(m => m.Id == model.Movies.Id);
movieInTable.Budget = model.Movies.Budget;
movieInTable.Writer = model.Movies.Writer;
movieInTable.Country = model.Movies.Country;
movieInTable.Genre = model.Movies.Genre;
movieInTable.Duration = model.Movies.Duration;
movieInTable.Plot = model.Movies.Plot;
movieInTable.Name = model.Movies.Name;
movieInTable.ProHouseId = model.Movies.ProHouseId;
movieInTable.Rating = model.Movies.Rating;
movieInTable.Director = model.Movies.Director;
movieInTable.Year = model.Movies.Year;
movieInTable.TitleURL = model.Movies.TitleURL;
}
Firstly, the written code is hard to reuse and you will have difficulties during the maintenance. Suppose a situation that you are repeating such code and use it in several files, suddenly you discover that another field is required and needs to be added. So you have to alter all the codes.
Second, it is recommended to not put your Data Manipulation codes in controller. Try to create another layer (class project) in order to put such codes. Using Automapper class library with absolutely help you reducing mappings.
Otherwise, as Travis suggested above, you can use a constructor in order to fill the properties.

How to get value of custom EF6 Designer property

I have succesfully extended the EF6 designer to allow for some custom properties on my entities, associations and properties using this post:
Extending Entity Framework 6 - adding custom properties to entities in designer
Now I need to use these custom properties when generating code in T4 but I have no clue how to access that information. Can someone point me in the right direction ?
regards,
Jurjen.
I've figured it out.
looking at, for instance, the entity variable in "foreach (var entity in typeMapper.GetItemsToGenerate(itemCollection))", this is a GlobalItem (https://msdn.microsoft.com/en-us/library/system.data.metadata.edm.globalitem(v=vs.110).aspx) wich contains MetadataProperties.
Listing these properties using a simple foreach
foreach( var mp in entity.MetadataProperties)
{
this.WriteLine("{0} = '{1}'", mp.Name, mp.Value);
}
results in a list
Name = 'Role'
NamespaceName = 'Model1'
Abstract = 'False'
...
http://saop.si:RecordTracked = '<a:RecordTracked xmlns:a="http://saop.si">true</a:RecordTracked>'
http://saop.si:DisplayMember = '<a:DisplayMember xmlns:a="http://saop.si">true</a:DisplayMember>'
as you can see, the custom properties (RecordTracked, DisplayName) are listed as well.
I have created 2 functions in within public class CodeStringGenerator to retrieve any custom property. Call it like this :
CodeStringGenerator.GetCustomPropertyAsBoolean(entity, "RecordTracked");
private bool GetCustomPropertyAsBoolean(GlobalItem item, string propertyName)
{
var _value = GetCustomProperty(item, propertyName);
if (string.IsNullOrEmpty(_value ))
{ return false; }
return _value.Equals("true", StringComparison.CurrentCultureIgnoreCase);
}
private string GetCustomProperty(GlobalItem item, string propertyName)
{
var _found = item.MetadataProperties.FirstOrDefault(p => p.Name.StartsWith("http://") &&
p.Name.EndsWith(propertyName, StringComparison.CurrentCultureIgnoreCase ));
if (_found == null)
{ return string.Empty; }
var _value = _found.Value as System.Xml.Linq.XElement;
if (_value == null)
{ return string.Empty; }
return _value.Value;
}

ASP MVC DevExpress: GridViewSettings in Controller rather than View

I just started working with ASP MVC using DevExpress, I've created views that have GridViews inside, and I had the settings in the partial view.
Short story
I need to have the GridViewSettings object inside a controller rather than the view.
Why? Because the app needs to download an Excel file of the grid and so far this is the only approach I've seen. But the problem is, having the grid settings in the controller doesn't allow me to specify a label inside an unbound column.
Here's the code:
public GridViewSettings MyGridSettings()
{
var settings = new GridViewSettings();
settings.Name = "MyGrid";
settings.CommandColumn.Visible = true;
settings.KeyFieldName = "PERSON_ID";
settings.SettingsPager.Visible = true;
settings.Settings.ShowGroupPanel = true;
settings.Settings.ShowFilterRow = true;
settings.SettingsBehavior.AllowSelectByRowClick = true;
settings.SettingsAdaptivity.AdaptivityMode = GridViewAdaptivityMode.HideDataCellsWindowLimit;
settings.SettingsAdaptivity.AdaptiveColumnPosition = GridViewAdaptiveColumnPosition.Right;
settings.SettingsAdaptivity.AdaptiveDetailColumnCount = 1;
settings.SettingsAdaptivity.AllowOnlyOneAdaptiveDetailExpanded = false;
settings.SettingsAdaptivity.HideDataCellsAtWindowInnerWidth = 0;
settings.Columns.Add("PERSON_ID", "Person ID");
settings.Columns.Add(col =>
{
col.Caption = "Department";
col.SetDataItemTemplateContent(dataTemplate =>
{
String DepartmenID = (String)DataBinder.Eval(dataTemplate.DataItem, "DEPARTMENT_ID");
//if (DepartmenID != null)
//{
// Html.DevExpress().Label(label =>
// {
// label.Text = String.Format("{0}",
// DataBinder.Eval(dataTemplate.DataItem, "DEPARTMENT.NAME"));
// }).Render();
// }
}
}
}
Short Question
How do I access the following code from a Controller?
Html.DevExpress().Label(label =>
{
label.Text = String.Format("{0}",
DataBinder.Eval(dataTemplate.DataItem, "DEPARTMENT.NAME"));
}).Render();
Like I said I need to do this because the Excel File Download. Although, if you have any workarounds where I don't need to do this that'd be great
Using HtmlHelper class described here (read Using HtmlHelper class section), probably this code may solve your issue:
public GridViewSettings MyGridSettings(this HtmlHelper html)
{
var settings = new GridViewSettings();
settings.Name = "MyGrid";
// simplified for brevity
settings.Columns.Add(col =>
{
col.Caption = "Department";
col.SetDataItemTemplateContent(dataTemplate =>
{
String DepartmentID = (String)DataBinder.Eval(dataTemplate.DataItem, "DEPARTMENT_ID");
if (DepartmentID != null)
{
html.DevExpress().Label(label =>
{
label.Text = String.Format("{0}", DataBinder.Eval(dataTemplate.DataItem, "DEPARTMENT.NAME"));
}).Render();
}
}
}
return settings;
}
Unlike views, controller actions doesn't have reference to HtmlHelper by default, hence you need to include HtmlHelper class inside GridViewSettings method to create HTML helper extensions.
In case your DataItemTemplateContent can't be exported by design, try exporting GridView contents to XtraReport using How to convert and then print an GridView extension by using the XtraReport example.
Additional references:
Grid View Exporting - 1
Grid View Exporting - 2

Ext.Net MVC refresh Panelgrid from controller

In my view have this:
#{
var properties = db.StylesPropertyDefs.OrderBy(o => o.PropertyId);
}
..
..
#(Html.X().GridPanel()
.Title("Array Grid")
.ID("propertyGrid")
.Width(600)
.Height(350)
.Store(Html.X().Store()
.Model(Html.X().Model()
.Fields(
new ModelField("PropertyId", ModelFieldType.Int),
new ModelField("PropertyName", ModelFieldType.String),
new ModelField("PropertyShortName", ModelFieldType.String),
new ModelField("PropertyActiveFlag", ModelFieldType.Boolean)
)
).DataSource(properties)
..
..
And i have an action in the controller to add new property. The new property is added successful but I can refresh the PanelGrid (without refresh the whole page). Here is the controller:
[DirectMethod]
public ActionResult AddNewProperty(string propertyName, string propertyCode, bool propertyActive)
{
if (propertyName == "" || propertyCode=="")
{
X.Msg.Show(new MessageBoxConfig
{
Title = "Error",
Message = "The field name or code can not be empty.",
Buttons = MessageBox.Button.OK,
Icon = MessageBox.Icon.ERROR
});
return this.Direct();
}
//if all is ok add new property
var newOne = new StylesPropertyDef
{
PropertyActiveFlag = propertyActive,
PropertyName = propertyName,
PropertyShortName = propertyCode
};
var db = new TaosKnowledgeDataContext(DataUtils.GetConStringLocal());
db.StylesPropertyDefs.InsertOnSubmit(newOne);
db.SubmitChanges();
//reload properties
var properties = db.StylesPropertyDefs.OrderBy(o => o.PropertyId);
var theGrid = X.GetCmp<GridPanel>("propertyGrid");
//now i need refresh or reload the panel grid.
X.GetCmp<Window>("AddNewProperty").Close();
return this.Direct();
//return RedirectToAction("StyleProperties");
}
So, resuming, I need refresh the PanelGrid datasource(or store) from the controller.
Please can you help me?
Please try the following.
Set up an ID for the Store.
.ID("Store1")
Do the following in the controller action.
Store store = X.GetCmp<Store>("Store1");
store.DataSource = db.StylesPropertyDefs.OrderBy(o => o.PropertyId);
store.DataBind();
Ok. I solve.
I deleted the Datasource in Store and I put a proxy reader to Controller.
.Proxy(
Html.X().AjaxProxy()
.Url(Url.Action("Read"))
.Reader(Html.X().JsonReader().Root("data"))
)
In the controller:
public ActionResult Read()
{
var db = new TaosKnowledgeDataContext(DataUtils.GetConStringLocal());
var properties = db.StylesPropertyDefs.OrderBy(o => o.PropertyId);
return this.Store(properties);
}
And when insert new Property:
var store = X.GetCmp<Store>("Store1");
store.Reload();
Thanks anyways.

Show only first error message

I am using ASP.NET MVC3 for a form that has both server and client validations. I'm showing error messages as balloons above the inputs. Due to the presentation of the errors, I need to only show one error at a time, otherwise the balloons tend to obscure other fields that may also be in error.
How can I customize the validation behavior to only render the first error message?
Edit: Please notice that the form has both server and client validations, and that I only want to show the first error message for the entire form (not per field).
In case anyone needs it, the solution I came up with is to add the following script towards the bottom of the page. This hooks into the existing javascript validation to dynamically hide all but the first error in the form.
<script>
$(function() {
var form = $('form')[0];
var settings = $.data(form, 'validator').settings;
var errorPlacementFunction = settings.errorPlacement;
var successFunction = settings.success;
settings.errorPlacement = function(error, inputElement) {
errorPlacementFunction(error, inputElement);
showOneError();
}
settings.success = function (error) {
successFunction(error);
showOneError();
}
function showOneError() {
var $errors = $(form).find(".field-validation-error");
$errors.slice(1).hide();
$errors.filter(":first:not(:visible)").show();
}
});
</script>
Could give this a shot on your controller action
var goodErrors = ModelState.GroupBy(MS => MS.Key).Select(ms => ms.First()).ToDictionary(ms => ms.Key, ms => ms.Value);
ModelState.Clear();
foreach (var item in goodErrors)
{
ModelState.Add(item.Key, item.Value);
}
I'm just selecting only one of each property error, clearing all errors then adding the individual ones back.
this is completely untested but should work.
You could create a custom validation summary which would display only the first error. This could be done either by creating an extension for the HtmlHelper class, or by writing your own HtmlHelper. The former is the more straightforward.
public static class HtmlHelperExtensions
{
static string SingleMessageValidationSummary(this HtmlHelper helper, string validationMessage="")
{
string retVal = "";
if (helper.ViewData.ModelState.IsValid)
return "";
retVal += #"<div class=""notification-warnings""><span>";
if (!String.IsNullOrEmpty(validationMessage))
retVal += validationMessage;
retVal += "</span>";
retVal += #"<div class=""text"">";
foreach (var key in helper.ViewData.ModelState.Keys)
{
foreach(var err in helper.ViewData.ModelState[key].Errors)
retVal += "<p>" + err.ErrorMessage + "</p>";
break;
}
retVal += "</div></div>";
return retVal.ToString();
}
}
This is for the ValidationSummary, but the same can be done for ValidationMessageFor.
See: Custom ValidationSummary template Asp.net MVC 3
Edit: Client Side...
Update jquery.validate.unobstrusive.js. In particular the onError function, where it says error.removeClass("input-validation-error").appendTo(container);
Untested, but change that line to: error.removeClass("input-validation-error").eq(0).appendTo(container);
Create a html helper extension that renders only one message.
public static MvcHtmlString ValidationError(this HtmlHelper helper)
{
var result = new StringBuilder();
var tag = new TagBuilder("div");
tag.AddCssClass("validation-summary-errors");
var firstError = helper.ViewData.ModelState.SelectMany(k => k.Value.Errors).FirstOrDefault();
if (firstError != null)
{
tag.InnerHtml = firstError.ErrorMessage;
}
result.Append(tag.ToString());
return MvcHtmlString.Create(result.ToString());
}
Update the jquery.validate.unobtrusive.js OnErrors function as below,
function onErrors(form, validator) { // 'this' is the form element
// newly added condition
if ($(form.currentTarget).hasClass("one-error")) {
var container = $(this).find(".validation-summary-errors");
var firstError = validator.errorList[0];
$(container).html(firstError.message);
}
else {
var container = $(this).find("[data-valmsg-summary=true]"),
list = container.find("ul");
if (list && list.length && validator.errorList.length) {
list.empty();
container.addClass("validation-summary-errors").removeClass("validation-summary-valid");
$.each(validator.errorList, function () {
$("<li />").html(this.message).appendTo(list);
});
}
}
}
Basically we have added a condition in the OnError to check whether the form contains a css-class named one-error and if yes then displays a single error else display all.

Resources