Is it possible to access more than one IViewComponentResult method in a single ViewComponent Class? I seem to be able to create more then one method with each referencing their own View, but I have been unable to find a way to reference the individual methods within the class from a razor view.
public class PageHeaderViewComponent: ViewComponent
{
public IViewComponentResult Header(LayoutModel layoutModel)
{
return View("Header", layoutModel);
}
public IViewComponentResult PageHeaderUpper(LayoutModel layoutModel)
{
return View("PageHeaderUpper", layoutModel);
}
}
I suggest you can pass a parameter to Invoke method to conditionally return different view:
public class PageHeaderViewComponent : ViewComponent
{
public IViewComponentResult Invoke(LayoutModel layoutModel,string name)
{
if(name=="header")
{
return View("Header", layoutModel);
}
else
{
return View("PageHeaderUpper", layoutModel);
}
}
}
You can invoke the view components like below in main view:
#await Component.InvokeAsync(typeof(PageHeaderViewComponent), new { LayoutModel= new LayoutModel() , name = "header" })
#await Component.InvokeAsync(typeof(PageHeaderViewComponent), new { LayoutModel= new LayoutModel() , name = "aaa" })
View Components location:
Besides, you can also use the property in LayoutModel as the condition.
Related
I have a class with a collection that needs validation. The generic on the collection takes an interface and different types can be added to the collection.
What is the cleanest path forward to creating a FluentValidation validator that supports polymorphism?
public interface IWizardStep {}
public class WizardOne : IWizardStep
{
public string Model { get; set; }
}
public class WizardTwo : IWizardStep
{
public string FirstName { get; set; }
}
public class Wizard
{
public Wizard()
{
var w1 = new WizardOne();
var w2 = new WizardTwo();
Steps = new List<IWizardStep>
{
w1,
w2
};
}
public IList<IWizardStep> Steps { get; set; }
}
public class WizardValidator : AbstractValidator<Wizard>
{
public WizardValidator()
{
RuleFor(x => x.Steps)
// Steps First where is WizardOne
// Model.NotEmpty()
// Steps First where is WizardTwo
// FirstName.NotEmpty()
}
FluentValidation doesn't support polymorphism for child collections like this out of the box, but you can add this behaviour by using a custom property validator, or by using OfType in your rule definitions.
I've written about both approaches before here:
Step 1: Create a validator for each implementor
Start by creating a validator for WizardOne and WizardTwo:
public class WizardOneValidator : AbstractValidator<WizardOne> {
public WizardOneValidator() {
RuleFor(x => x.Model).NotEmpty();
}
}
public class WizardTwoValidator : AbstractValidator<WizardTwo> {
public WizardTwoValidator() {
RuleFor(x => x.FirstName).NotEmpty();
}
}
Step 2: Create the parent validator
You have two options for defining the parent validator. The simplest approach is to use OfType, but this is less performant. The more complex option is to use a custom property validator.
Option 1: Using OfType
public WizardValidator : AbstractValidator<Wizard> {
public WizardValidator() {
RuleForEach(x => x.Steps.OfType<WizardOne>()).SetValidator(new WizardOneValidator());
RuleForEach(x => x.Steps.OfType<WizardTwo>()).SetValidator(new WizardTwoValidator());
}
}
This is the simplest approach, but calling OfType inside the call RuleFor will end up bypassing FluentValidation's expression cache, which is a potential performance hit. It also iterates the collection multiple. This may or may not be an issue for you - you'll need to decide if this has any real-world impact on your application.
Option 2: Using a custom PropertyValidator.
This uses a custom custom validator which can differentiate the underlying type at runtime:
public WizardValidator : AbstractValidator<Wizard> {
public WizardValidator() {
RuleForEach(x => x.Steps).SetValidator(new PolymorphicValidator<Wizard, IWizardStep>()
.Add<WizardOne>(new WizardOneValidator())
.Add<WizardTwo>(new WizardTwoValidator())
);
}
}
Syntactically, this isn't quite as nice, but doesn't bypass the expression cache and doesn't iterate the collection multiple times. This is the code for the PolymorphicValidator:
public class PolymorphicValidator<T, TInterface> : ChildValidatorAdaptor<T, TInterface> {
readonly Dictionary<Type, IValidator> _derivedValidators = new Dictionary<Type, IValidator>();
// Need the base constructor call, even though we're just passing null.
public PolymorphicValidator() : base((IValidator<TInterface>)null, typeof(IValidator<TInterface>)) {
}
public PolymorphicValidator<T, TInterface> Add<TDerived>(IValidator<TDerived> derivedValidator) where TDerived : TInterface {
_derivedValidators[typeof(TDerived)] = derivedValidator;
return this;
}
public override IValidator<TInterface> GetValidator(PropertyValidatorContext context) {
// bail out if the current item is null
if (context.PropertyValue == null) return null;
if (_derivedValidators.TryGetValue(context.PropertyValue.GetType(), out var derivedValidator)) {
return new ValidatorWrapper(derivedValidator);
}
return null;
}
private class ValidatorWrapper : AbstractValidator<TInterface> {
private IValidator _innerValidator;
public ValidatorWrapper(IValidator innerValidator) {
_innerValidator = innerValidator;
}
public override ValidationResult Validate(ValidationContext<TInterface> context) {
return _innerValidator.Validate(context);
}
public override Task<ValidationResult> ValidateAsync(ValidationContext<TInterface> context, CancellationToken cancellation = new CancellationToken()) {
return _innerValidator.ValidateAsync(context, cancellation);
}
public override IValidatorDescriptor CreateDescriptor() {
return _innerValidator.CreateDescriptor();
}
}
}
This will probably be implemented in the library as a first class feature at some point in the future - you can track its development here if you're interested.
If I want to use a Table from a DataContext, I need to instantiate it:
Table<Customer> customers = db.GetTable<Customer>();
But if it's in a custom DataContext:
public partial class Northwind : DataContext
{
public Table<Customer> Customers;
...
}
I can just use it like this:
Table<Customer> customers = db.Customers;
Where is it instantiated?
Based on the documentation, it is just a property getter that return this.GetTable<TEntity>().
Eg.
public partial class DataClasses1DataContext : System.Data.Linq.DataContext {
public System.Data.Linq.Table<User> Users {
get {
return this.GetTable<User>();
}
}
}
public class AController : Controller
{
public ActionResult Index()
{
return View();
}
}
and Index view goes like
...
#Html.Action("Index", "BController", new { HasEditPermission = true })
...
BControler goes like
public class BController : Controller
{
public ActionResult Index()
{
return PartialView();
}
}
and this Index Partial view goes like
...
#if (!string.IsNullOrEmpty(Request.Params["HasEditPermission"]) && bool.Parse(Request.Params["HasEditPermission"]))
{
// some html rendering
}
...
here when I do Request.Params["HasEditPermission"] in the partial view, I get null.. but if I include HasEditPermission as a parameter to my Index action of BController then I get the value..
I think, I am not getting it from Request.Params because actual request is to AController Index action which doesn't include this parameter.
But I am wondering how is it binding the value to HasEditPermission parameter of Index action(suppose if I have it there) of BController?
Please could someone tell me how do I access it directly in the view? (I am aware using ViewBag in Index is an option)
You can use ValueProvider.GetValue("HasEditPermission").RawValue to access the value.
Controller:
public class BController : Controller
{
public ActionResult Index()
{
ViewBag.HasEditPermission = Boolean.Parse(
ValueProvider.GetValue("HasEditPermission").RawValue.ToString());
return PartialView();
}
}
View:
...
#if (ViewBag.HasEditPermission)
{
// some html rendering
}
...
Update:
Request.Params gets a combined collection of QueryString, Form, Cookies, and ServerVariables items not RouteValues.
In
#Html.Action("Index", "BController", new { HasEditPermission = true })
HasEditPermission is a RouteValue.
you can also try something like this
ViewContext.RouteData.Values["HasEditPermission"]
in your View and subsequent child action views as well..
i have a class (in project by mvc4 razor on .net 4.5) and want to handle a Redirecting method on it and do not want inherit from controller class.
how can i handle this?it returns ActionResult to redirecting user in some cases like log outing
my main class:
public class SecuritySrv
{
public ActionResult Redirect()
{
return RedirectToAction("Logout", "Account", new { area = "" });
}
}
and i want to use it in some controllers like below:
public ActionResult AccountHome()
{
SecuritySrv SecurityService =new SecuritySrv()
if(.....)
return SecurityService.Redirect();
return view();
}
You can use this code anywhere, and you don't need an UrlHelper or access to the context, so you don't need to inherit the Controller class.
RouteValueDictionary rvd = new RouteValueDictionary
{
{"controller", "Profile"},
{"action", "Users"},
{"area", ""}
};
return new RedirectToRouteResult(rvd);
The RedirectToAction method of controller is just a helper for creating RedirectToRouteResult, you can create it by yourself in your class:
public class SecuritySrv
{
public ActionResult Redirect()
{
RouteValueDictionary routeValues = new RouteValueDictionary();
routeValues["action"] = "Logout";
routeValues["controller"] = "Account";
routeValues["area"] = "";
return new RedirectToRouteResult(routeValues);
}
}
And call this method from your controller in the way you wanted to.
With the following:
public class AClass
{
public ADependent Dependent { get; set; }
}
public class ADependent
{
public ADependent(AClass ownerValue) {}
}
with the following registrations...
builder.RegisterType<AClass>().PropertiesAutowired().InstancePerDependency();
builder.RegisterType<ADependent>().PropertiesAutowired().InstancePerDependency();
When I resolve an AClass, how do I make sure that 'ownerValue' is the instance of AClass being resolved, and not another instance? Thx
FOLLOW ON
The example above doesn't really catch the problem properly, which is how to wire up ADependent when registering when scanning... for example
public class AClass : IAClass
{
public IADependent Dependent { get; set; }
}
public class ADependent : IADependent
{
public ADependent(IAClass ownerValue) {}
}
// registrations...
builder.RegisterAssemblyTypes(assemblies)
.AssignableTo<IAClass>()
.As<IAClass>()
.InstancePerDependency()
.PropertiesAutowired();
builder.RegisterAssemblyTypes(assemblies)
.AssignableTo<IADependent>()
.As<IADependent>()
.InstancePerDependency()
.PropertiesAutowired();
The function I am looking for really is another relationship type like
public class ADependent : IADependent
{
public ADependent(OwnedBy<IAClass> ownerValue) {}
}
The OwnedBy indicates that ownerValue is the instance that caused ADependent to created. Does something like this make sense? It would certainly make wiring up UI components a breeze.
To extend Steven's approach, you can even Resolve() the second class, passing the first instance as a parameter:
builder.RegisterType<ADependent>();
builder.Register<AClass>(c =>
{
var a = new AClass();
a.Dependent = c.Resolve<ADependent>(TypedParameter.From(a));
return a;
});
You can register a lambda to do the trick:
builder.Register<AClass>(_ =>
{
var a = new AClass();
a.Dependent = new ADependent(a);
return a;
});