Sitecore using Glass mapper and MVC - asp.net

Hi am using the Glass mapper in combination with Sitecore MVC. I created model below.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace Test
{
using Glass.Mapper.Sc.Configuration.Attributes;
[SitecoreType(AutoMap = true)]
public class GlassTestModel
{
public virtual string Title { get; set; }
}
}
this is my view
#inherits Glass.Mapper.Sc.Web.Mvc.GlassView<Test.GlassTestModel>
<div>
<h2>Hello</h2>
<h2>#Model.Title</h2>
</div>
I also tried this first line
#model Test.GlassTestModel
and this one
#inherits System.Web.Mvc.WebViewPage<Test.GlassTestModel>
I created a view rendering in Sitecore. configured the model to use above.
When I render the view the model fields don't get filled. When I test in a controller I use for other controller view like below:
ISitecoreContext ctx = new SitecoreContext();
var item = ctx.GetCurrentItem<Test.GlassTestModel>();
I do get the title field. Any ideas?

I migrated my solution to V4 of the Glass.Mapper package. This works. With V3 I can't get the automapping to work.

Related

Acumatica How to customize Time Entries and Activities with Custom Selector Field

We want to customize the time entries and activities logic to have a custom selector field that pulls information from an attribute that is setup in the system. It has to be a required field if the TimeSpent and BilledTime does not match, the entry is marked as billable, and the project has a customer loaded against it. I have successfully managed to get it working on the Employee Time Activities screen, but I am trying to use that same custom field on the Activities popup dialog. I also get an error when adding an Activity directly to project, which states that the Time Entry requires a Reason Code but I don't have access to add it to the list to display on the Activities Panel/Dialog.
See screenshots below:
Ignore the Activity Reason Code, this is an additional custom field I added to test the customization.
I want to add my custom field in here:
Below is the extention class DAC.
using PX.Data;
using PX.Objects.CS;
using PX.Objects.PM;
using iPlanReasonCode.Helpers;
namespace PX.Objects.CR
{
public class PMTimeActivityExt : PXCacheExtension<PX.Objects.CR.PMTimeActivity>
{
#region UsrReasonCode
[PXDBString]
[PXUIField(DisplayName = "Reason Code")]
[PXDefault]
[PXSelector(typeof(Search<CSAttributeDetail.valueID, Where<CSAttributeDetail.attributeID.IsEqual<ReasonCodeAttributeID>>>),
typeof(CSAttributeDetail.valueID), typeof(CSAttributeDetail.description), SubstituteKey = typeof(CSAttributeDetail.valueID), DescriptionField = typeof(CSAttributeDetail.description))]
[PXUIRequired(typeof(Where<PMTimeActivity.isBillable.IsEqual<True>.And<PMTimeActivity.timeSpent.IsNotEqual<PMTimeActivity.timeBillable>>.And<Where<Selector<PMTimeActivity.projectID, PMProject.customerID>, IsNotNull>>>))]
public virtual string UsrReasonCode { get; set; }
public abstract class usrReasonCode : PX.Data.BQL.BqlString.Field<usrReasonCode> { }
#endregion
}
}
Below is the helper constant class to point it to the correct attribute code.
using PX.Data;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace iPlanReasonCode.Helpers
{
public class ReasonCodeAttributeID : PX.Data.BQL.BqlString.Constant<ReasonCodeAttributeID>
{
public ReasonCodeAttributeID()
: base("CUSTREASON")
{ }
}
}
So this one is a bit tricky, for some reason Acumatica's "Add data fields" on the customization project browser does not recognize the "TimeActivity" view, which is the view in which your field is added to (on PMTimeActivity).
What you should do if you want to keep the field on this record is manually edit the ASPX, find the area of the page where you see fields referencing Datafield="TimeActivity.***" and manually add an XML Tag and reference the timeactivity data view the same way e.g. DataField="TimeActivity.UsrYourCustomField"
Textbox:
<px:PXTextEdit ID="chkYourField" runat="server" DataField="TimeActivity.UsrYourCustomField" />
Checkbox:
<px:PXCheckBox ID="chkYourField" runat="server" DataField="TimeActivity.UsrYourCustomField" />
After you manually add the tag, then you will be able to move it around using the UI
If you want to skip over all of this and just make it easy, move your custom field to the CRActivity DAC

How to create the code behind of Razor page

When I create a new Razor page in Visual Studio 2017, the separated code behind file did not get created.
This is the screenshot of the problem highlighted.
We can see the Razor page called List.cshtml does not contain the code behind file. Contrast that with the default page about.cshtml, for example.
1 - Right click on "resturants", add class:
2 - in your case, call it List.cshtml.cs. This will create the code behind. It nows needs wiring up. Open the class that has been created.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
//Add the MVC usings
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
//TODO The namespace will be correct in your code
namespace app_name.Pages.resturants
{
//public class List
//TODO correct the model name and inherit PageModel
public List1Model : PageModel
{
public void OnGet()
{
}
}
}
3 - In List.cshtml:
#page
#model app_name.Pages.resturants.List1Model
#{
}
More information can be found here on modifying the code behind https://learn.microsoft.com/en-gb/aspnet/core/data/ef-rp/sort-filter-page?view=aspnetcore-5.0

ASP.NET MVC 3 Partial View in layout page

I'm working on setting up a shared content (navigation) for an asp.net MVC layout page.
Here is my partial view "_LayoutPartial.cshtml" with code to pull navigation data from a model.
#model MyApp.Models.ViewModel.LayoutViewModel
<p>
#foreach (var item in Model.navHeader)
{
//Test dump of navigation data
#Html.Encode(item.Name);
#Html.Encode(item.URL);
}
</p>
Here is how the code for my controller "LayoutController.cs" looks like.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MyApp.Models.ViewModel;
namespace MyApp.Controllers
{
public class LayoutController : Controller
{
//
// GET: /Layout/
LayoutViewModel layout = new LayoutViewModel();
public ActionResult Index()
{
return View(layout);
}
}
}
Here is the code for the "_Layout.cshtml" page. I'm attempting to call the partial view here using Html.RenderAction(Action,Controller) method.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<p>
#{Html.RenderAction("Index","Layout");}
</p>
#RenderBody()
</body>
</html>
When the layout page executes the #{Html.RenderAction("Index","Layout");} line, it throws out an error message "Error executing child request for handler 'System.Web.Mvc.HttpHandlerUtil+ServerExecuteHttpHandlerAsyncWrapper'."
What am I missing friends? How can I call a partial view in a layout page?
Thank you all in advance!
Instead of:
public ActionResult Index()
{
return View(layout);
}
do:
public ActionResult Index()
{
return PartialView(layout);
}
If you don't do that when you return a normal view from your child action, this normal view attempts to include the Layout, which in turn attempts to render the child action, which in turn returns a view, which in turn includes the Layout, which in turn attempts to render the child action, ... and we end up with names like the one ported by this very same site.
Also in your partial you don't need to do double encoding. The # Razor function already does HTML encode:
#model MyApp.Models.ViewModel.LayoutViewModel
<p>
#foreach (var item in Model.navHeader)
{
#item.Name
#item.URL
}
</p>
First verify that your child view is inside the Shared directory
#Html.Partial("_LayoutPartial")
OR
#{Html.RenderAction("actionname", "controller name");}
And don't use #Html.Encode(), Razor is already doing for u. Just use
#item.Name
#item.URL
I have solved this error getting on Layout page
System.Web.Mvc.HttpHandlerUtil+ServerExecuteHttpHandlerAsyncWrapper
Important !
First create partial view inside shared folder
In Controller ,
public PartialViewResult Userdetails()
{
....
return PartialView("PartialViewName", obj);
}
In Layout Page,
#{Html.RenderAction("action","controller");}
I know this is an old question but I thought I would throw this in here. You can use either Html.Action or Html.RenderAction. They both technically do the same thing but depending on how much content you're returning back can have an impact on which one you should really use for best efficiency.
Both of the methods allow you to call into an action method from a view and output the results of the action in place within the view. The difference between the two is that Html.RenderAction will render the result directly to the Response (which is more efficient if the action returns a large amount of HTML) whereas Html.Action returns a string with the result.
Source

Validation on int data type asp .net mvc3

I am getting The value 'abc' is not valid for fieldName. as error message. which is default error message and i want to override it in easier way.as of now what i have tried is listed below
[RegularExpression(#"^\d+$",ErrorMessage="enter numeric value")]
[Integer(ErrorMessageResourceType = typeof(appName.Resources.abc.Resource),
ErrorMessageResourceName = "error_numeric")]
[RegularExpression("([1-9][0-9]*)")]
Range(1,int.max,ErrorMessage="enter numeric value")
but failed to change default error message.
Suggest me the easiest possible way to do this.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
namespace blueddPES.ViewModels
{
public class ContactViewModel
{
[Integer(ErrorMessage="sdfdsf")]
public int? hp { get; set; }
}
Easiest way is to use Data Annotations Extensions. It has some useful attributes for things like Integers, etc.
Or you could write your own, like in: How to change 'data-val-number' message validation in MVC while it generate by helper
Edit: Added complete sample after comments.
I created a sample vanilla MVC 3 project and then did the following:
Added NuGet package DataAnnotationsExtensions.MVC3
Added a Model class:
public class IntegerSample
{
[Required(ErrorMessage="Dude, please fill something in!")]
[Integer(ErrorMessage="Are you stupid? Just fill in numbers only!")]
public int? TestValue { get; set; }
}
Added a Home Controller:
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
return View();
}
}
Added a Home View:
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>IntegerSample</legend>
<div class="editor-label">
#Html.LabelFor(model => model.TestValue)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.TestValue)
#Html.ValidationMessageFor(model => model.TestValue)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
I hope you get some more insights using this sample code. When I run this sample, it works just as you'd want to expect.
You could implement a custom model binder as shown here or use a string datatype instead of integer and then apply the regular expression data annotation. Of course if you use a string datatype you might need to parse this string manually to the underlying datatype when mapping your view model to a domain model.
We use an extended version of Phil Haack MetadataProvider which can do localization.
Take at look at this blog article: http://haacked.com/archive/2011/07/14/model-metadata-and-validation-localization-using-conventions.aspx
In summary:
It determines a resource key by using the class type + property, e.g. Person_FirstName
It looks up error messages by suffixing the validation property, e.g. Person_FirstName_Required
You just supply the resource file with those entries.

Attribute 'DisplayColumn' is not valid on this declaration type. It is only valid on 'class' declarations

Just wondering why I get compile time error :
"Attribute 'DisplayColumn' is not valid on this declaration type. It is only valid on 'class' declarations."
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
namespace MyApplication.Models.DataAnnotations
{
[MetadataType(typeof(AppUser_DataAnnotations))]
public partial class AppUser
{
}
public class AppUser_DataAnnotations
{
[DisplayColumn("Name")]
public string FirstName { get; set; }
}
}
I'm using above to override mvccontrib rendered grid column headers. Any idea why I get compile time error? Any help would be greatly appreciated.
For people who run into this problem in the future maybe this can help:
I got the same problem as described above. As described in other answers it is important to use the DisplayName property and to include the System.ComponentModel namespace. Besides that, the property must have a getter (and setter) to get the attribute working. The errormessage is a bit confusing on this one.
The reason you are getting a compile-time error is because the [DisplayColumn] attribute can only be applied at the class level and not at a property of the class. You are probably confusing this attribute with [DisplayName].
You can also run into this problem when you decorate a Model Property with the attribute.
You need to decorate Controller Method's with ActionFilterAttribute's not property's.

Resources