ASP.NET MVC3 Fluent Validation Constructor hit multiple times per request - asp.net-mvc-3

I have an ASP.NET MVC3 website setup using fluent validation and ninject. The validation code is working. However, I set a break point in the validation class constructor and I noticed that when I request my view that uses the validation the constructor gets hit multiple times. Based on very basic testing it seems that the number of times the constructor is hit is equal to the number of properties that exist on the object. Has anyone else come across something similar? Or can someone shed more insight on how this type of validation works behind the scenes? -Thanks
Here is the constructor...
public class PersonValidator : AbstractValidator<Person> {
public PersonValidator() {
RuleFor(x => x.Id).NotNull();
RuleFor(x => x.Name).Length(0, 10);
RuleFor(x => x.Email).EmailAddress();
RuleFor(x => x.Age).InclusiveBetween(18, 60);
}
}
Here are the libraries/resources that I am using (I just got the NuGet packages and configured everything based on the info from the two links below):
http://fluentvalidation.codeplex.com/wikipage?title=mvc
https://github.com/ninject/ninject.web.mvc.fluentvalidation

I figured out how to prevent this issue. Even though this solves my issue, I would like input from others on whether there are any consequences in doing this?
So on the second link you will see instructions on how to set up Ninject.
On the second step you need to apply the "InRequestScope()" extension method. Then the constructor will only be hit once per http request that uses your validator. That obviously means that only one instance of the validator object is created per http request, which makes sense to me. I don't know if there are any consequences to using this solution?
Bind(match.InterfaceType).To(match.ValidatorType).InRequestScope();

Resurrecting this thread.
I had the same problem with SimpleInjector. My solution was include LifeTime.Scoped on the collection register.
private static void WarmUpMediatrAndFluentValidation(this Container container)
{
var allAssemblies = GetAssemblies();
container.RegisterSingleton<IMediator, Mediator>();
container.Register(typeof(IRequestHandler<,>), allAssemblies);
RegisterHandlers(container, typeof(INotificationHandler<>), allAssemblies);
RegisterHandlers(container, typeof(IRequestExceptionAction<,>), allAssemblies);
RegisterHandlers(container, typeof(IRequestExceptionHandler<,,>), allAssemblies);
//Pipeline
container.Collection.Register(typeof(IPipelineBehavior<,>), new[]
{
typeof(RequestExceptionProcessorBehavior<,>),
typeof(RequestExceptionActionProcessorBehavior<,>),
typeof(RequestPreProcessorBehavior<,>),
typeof(RequestPostProcessorBehavior<,>),
typeof(PipelineBehavior<,>)
});
container.Collection.Register(typeof(IRequestPreProcessor<>), new[] {typeof(EmptyRequestPreProcessor<>)});
container.Collection.Register(typeof(IRequestPostProcessor<,>), new[] {typeof(EmptyRequestPostProcessor<,>)});
container.Register(() => new ServiceFactory(container.GetInstance), Lifestyle.Singleton);
container.Collection.Register(typeof(IValidator<>), allAssemblies, Lifestyle.Scoped);
}
container.Collection.Register(typeof(IValidator<>), allAssemblies, Lifestyle.Scoped); <- Workers fine for me, calling only once per request.

Related

"the UmbracoHelper was constructed with an UmbracoContext and the current request is not a front-end request."

I'm trying to implement ajax pagination using Umbraco.
On the server side, I have the following:
[System.Web.Http.HttpGet]
public JsonResult pagination(int? page)
{
IEnumerable<IPublishedContent> newsPosts = Umbraco.AssignedContentItem.DescendantOrSelf("news").Children.Where(x => x.IsVisible() && x.DocumentTypeAlias == "newsPost").OrderByDescending(x => x.UpdateDate).Take(5);
//from here on we will be returning the json within which information required for displaying post entries in carousel is included.
string json = "[some random string]"; //just random string for now.
return Json(json, JsonRequestBehavior.AllowGet);
}
As you can see, I'm trying to get necessary data from IPublishedContents, but I'm having trouble instantiating this series of IPublishedContents.
And this is the error I'm getting when I access:
locahost:{port}/umbraco/surface/{controller}/pagination on Chrome.
Cannot return the IPublishedContent because the UmbracoHelper was constructed with an UmbracoContext and the current request is not a front-end request.
Details: System.InvalidOperationException: Cannot return the IPublishedContent because the UmbracoHelper was constructed with an UmbracoContext and the current request is not a front-end request.
As I said, I'm making this request from Chrome, which is I think means this request is from the front end, so I'm not sure why I'm getting this error.
In the course of searching I found these
1) our.umbraco.com forum
2) stackoverflow post
is deserted with no answer, and as for 2, it strikes me that the answer is not quite relevant to my case. I want to instantiate IPublishedContent in the first place.
Mine is Umbraco 7.
and could it be possible to tell me why requests from the front-end are not desirable?
Any hint would be highly appreciated.
Thanks,
Try getting your node this way.
var umbracoHelper = new Umbraco.Web.UmbracoHelper(Umbraco.Web.UmbracoContext.Current);
var yourNode = umbracoHelper.TypedContentAtXPath("umbracoPathtoYourNode");
Perhaps easier to use web api
Create a controller which inherits from UmbracoApiController
public class PagedItemsController : UmbracoApiController
{
[HttpGet]
[ActionName("list")] //Optional see note below
public IHttpActionResult GetItems([FromUri] int pageNo = 1)
{
// Next you need some way of getting the items you need.
// I would not return the whole IPublishedContent items. Rather query those and then use linq Select to transform into a more relevant smaller class (not doing this here)
// I've just included this for brevity
var items = _itemService.GetPagedItems(pageNo);
// Now return the results
return Ok(items);
}
}
Calls to endpoints in Umbraco follow the format
/umbraco/api/{controller}/{endpoint}
With the [ActionName("list")] above the call to the GetItems method will be
http://example.com/umbraco/api/PagedItems/list?pageNo=3
Without the ActionName attribute the call would be
http://exampe.com/umbraco/api/PagedItems/GetItems?pageNo=3
With a standard jquery ajax call this will return json without needing to serialise.

Web API in MVC 6 is missing $id

I have noticed that compared to Web API in MVC 5, where each object returned includes an $id property, in MVC 6 no such id is returned. Since my client side code makes use of this property, is there any setting to enable it to be returned in MVC 6?
I think that you formulate the question not full correctly, but I suppose that you can have the same result as before if you would modify ConfigureServices method of Startup.cs. Try to set PreserveReferencesHandling used by Newtonsoft.Json to the value PreserveReferencesHandling.Objects:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc()
.AddJsonOptions(options => {
options.SerializerSettings.PreserveReferencesHandling =
PreserveReferencesHandling.Objects;
});
...
}
Such setting will don't add $id in really all object, but I think it should work in the cases, which you used before.

How to override a web api route?

I am trying to standardize an extension model for our REST API development team. We need to provide default implementation of routes, while allowing for custom implementations of routes that replace the default as well.
As a simple example if we have a GET route api/users like this:
public class DefaultUsersController : ApiController
{
[HttpGet]
[Route("api/users", Order = 0)]
public IEnumerable<string> DefaultGetUsers()
{
return new List<string>
{
"DefaultUser1",
"DefaultUser2"
};
}
}
We expect the default work like this:
Now a developer wants to change the behavior of that route, he should be able to simply define the same route with some mechanism to imply their implementation should be the one used, instead of the default. My initial thinking was to use the Order property on the Route attribute since that's what it appears to be there for, as a way to provide a priority (in ascending order) when an ambiguous route is discovered. However it's not working that way, consider this custom implementation that we want to override the default api/users route:
public class CustomUsersController : ApiController
{
[HttpGet]
[Route("api/users", Order = -1)]
public IEnumerable<string> CustomGetUsers()
{
return new List<string>
{
"CustomUser1",
"CustomUser2"
};
}
}
Notice the Order property is set to -1 to give it a lower priority value than the default, which is set to 0. I would have thought this would be used by the DefaultHttpControllerSelector, but it isn't. From the DefaultHttpControllerSelector:
And we end up with this exception being returned in the response:
Is it possible Microsoft just missed the logic/requirement to use Order as a route disambiguator and this is a bug? Or is there another simple way to override a route, hopefully with an attribute?
I have pretty much the same problem. I am creating a starter site, but I want users to be able to redefine to behaviour of a Controller, especially if there is a bug.
I use Autofac to resolve the Controller, but even when I register the new controller as the old one, the original one gets selected.
What I'll do is probably go with URL Rewriting. Especially since this issue is temporary in my case. However, I would be interested if someone has a better option.

ASP.NET MVC3 app creating bad route value

OK, this may just me being ignorant, but I have the following route in my MVC3 application:
routes.MapRoute("Directory","{aid}/{controller}/{action}/{year}/{quarter}",
new { aid = "sf", controller = "Lobbyist", action = "Index",
year = CurrentYear(), quarter = CurrentQuarter() });
In my Global.asax.cs, I have these two methods:
public static int CurrentQuarter()
{
int quarter = 0;
//...use some internal business logic to determine the value of
//'quarter' based on the current date...
return quarter;
}
public static int CurrentYear()
{
return DateTime.Now.Year;
}
This code works great almost all the time. At one point in time, in our production environment (running IIS7), the route value for CurrentQuarter() became a value of zero, when it should have been 1, 2, 3, or 4. It works just fine in production except for that one point in time. An IISRESET 'fixed' the problem.
What I know:
At the time CurrentQuarter() was failing, CurrentYear() was still
returning correctly
The CurrentQuarter() method was not throwing an
exception which would have prevented setting the 'quarter' variable
The business logic which drives the CurrentQuarter() method works
for every date between DateTime.MinValue and DateTime.MaxValue
My question really gets down to is:
Is it BAD to call static methods to generate route values?
Is there a potential for the application to 'forget' the result of the static method, and cause it to return a garbage value? Could an application pool recycling cause this?
I'm sort of grasping at straws here!
Thanks for any advice.
I would not call static values here. I completely disagree with Igor above. Its not standard and is hard to track down where these values are coming from to someone that doesn't know the app. Call it either from your controller, or even better yet - a service layer (ie business logic) your controller calls to that gets this value.
A routes purpose is not to call a business method.
On the second question, if there is an app pool recycle, the value will simply be reset. However if multiple threads are calling into this method and potentially changing the value in the same method I would implement some locking in there to prevent updates from overlapping.
You should make the route values year and quarter optional, and provide default values for them in the Action method. I think this makes everything cleaner, and easier to maintain.
public class LobbyistController
{
public ActionResult Index(int? year, int? quarter)
{
if (!currentYear.HasValue)
{
currentYear = GetCurrentYear();
}
if (!currentQuarter.HasValue)
{
currentQuarter = GetCurrentQuarter();
}
// the rest
}
}

Accessing data in kohana validation

i'll try and be as clear as possible.
I'm working on some form validation using the wonderful kohana framework. However i have come at a crossroads and not sure whether the way i have taken is a wise choice.
Basically, i have a date selector using several select boxes (i toyed with the idea of using javascript date pickers but the select boxes proved to be more suitable for my purpose) and a date field in a database. I wanted to concatenate these select boxes into the date field so it can be checked to make sure its valid.
protected $_rules = array(
'mydate' => array(
'not_empty' => NULL,
'date' => NULL,
),
);
Now to me, it makes most sense to include the validation in the model, since that's where the data layer is in the MVC pattern, so i decided to create some class attributes named $_rules, $_filters and $_callbacks, each set as protected and with my basic rules applied. And then a function in the model that sets up a validation object using these attributes and returning it to whatever controller is calling it, then the controller can just run the validation and the job is done.
My problem comes when i want to concat these select boxes, to me it makes most sense to make a custom filter and pass in the post data, but with the filters rules and callbacks being attributes, i can't add any variables to them. My current solution is to manually add the extra filter in when the validation setup function is being run something similar to this:
public function setupValid($post) {
$this->_filters['mydatefield'] = array(
'MyClass::MyConcat' => array($post);
);
//creates a validation object and adds all the filters rules and callbacks
}
But i don't feel this is the cleanest solution, i'm probably nit picking as the solution works the way i require it to. However i'm not sure whether a filter was ever intended to do such a thing as this, or whether this should be a callback as the callback has access to the array by default, but then again callbacks are called last, which would mean i couldn't apply any rules like, 'not_empty' (not important in this case since they are pre populated select boxes, but might be in another case)
So i guess my question is, am i using filters as they were intended to be used?
I hope i've managed to explain this clearly.
Thanks
you need to keep in mind that you should only validate fields inside the $_rules that are very important to your database or business logic.
so for example if you would try to setup other form somewhere else in your app or you would provide a restfull api for your app, validation of the field 'day_field_(that_doesnt_exists_in_the_database_and_is_used_to_privide_a_better_ux_in_this_one_form)' => array('not_empty' => NULL) will give you a hard time to do that.
so i suggest you to keep your $_rules like they are now and provide some logic to your values() method:
// MODEL:
public function values($values)
{
if ( ! empty($values['day']) && ! empty($values['month']) && ! empty($values['year']))
{
$values['mydate'] = $values['year'].'-'.$values['month'].'-'.$values['day'];
}
return parent::values($values);
}
// CONTROLLER:
if ($orm->values($form['form_array'])->check())
{
$orm->save();
}
else
{
$this->template->errors = $orm->validate()->errors('validation');
}

Resources