I would like to write method validation processes which will be similar to data annontations presented in Web API.
In web api we can validate an object, for example:
public class Numbers
{
[NumberOne]
public string Number1 { get; set; }
[NumberTwo]
public string Number2 { get; set; }
}
and as long as we define the attributes NumberOneAttribute and NumberTwoAttribute its gonna be ok.
The difference is that web api has access to the GlobalConfiguration.Configuration.Filters which it seems like signalr doesn't.
Is there anyway to validate requests by attributes? or I need to follow the worst case, validate each input in the invoked method?
Thanks,
Ori.
In SignalR 2.2.x there is no native way of achieving this, but there is a project on GitHub that that adds a Validation Module in the SignalR pipeline.
Basically, in order to use it, you add a new module to the pipeline:
GlobalHost.HubPipeline.AddModule(new ValidationModule());
Then, you can use attributes like [Required] for the models' properties and then decorate the desired methods with the [Validate] attribute.
Note that this is a proof of contept project.
Best regards!
Related
.Net Core 3.0 MVC view. Needs to apply - Client Side validation for below model.
Tried as follow:
Model:Person
public class Person {
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public int Age { get; set; }
}
Validation Rules:
public class PersonValidator : AbstractValidator<Person> {
public PersonValidator() {
RuleFor(x => x.Id).NotNull().NotEmpty();
RuleFor(x => x.Name).Length(0, 10);
RuleFor(x => x.Email).EmailAddress();
RuleFor(x => x.Age).InclusiveBetween(18, 60);
}
}
Followed documentation, it shows, "validator" attribute but I could not find in namespace.
https://docs.fluentvalidation.net/en/latest/mvc5.html
Solution 1: Use AddFluentValidationClientsideAdapters
You may use the FluentValidation.AspNetCore and register the client-side validation by adding:
services.AddFluentValidationClientsideAdapters();
Solution 2: Use FormHelper
You may also use the FormHelper and, instead of using client-side validation you could instead execute your full server-side rules via AJAX.
Details
The FluentValidation GitHub readme says:
Clientside Validation
FluentValidation is a server-library and does not provide any
client-side validation directly. However, it can provide metadata
which can be applied to the generated HTML elements for use with a
client-side framework such as jQuery Validate in the same way that
ASP.NET's default validation attributes work.
Note that not all rules defined in FluentValidation will work with
ASP.NET's client-side validation. For example, any rules defined using
a condition (with When/Unless), custom validators, or calls to Must
will not run on the client side. Nor will any rules in a RuleSet
(although this can be changed - see below). The following validators
are supported on the client:
NotNull/NotEmpty
Matches (regex)
InclusiveBetween (range)
CreditCard
Email
EqualTo (cross-property equality comparison)
MaxLength
MinLength
Length
To enable clientside integration you need to install the
FluentValidation.AspNetCore package and call the
AddFluentValidationClientsideAdapters in your application startup:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddFluentValidationClientsideAdapters();
services.AddScoped<IValidator<Person>, PersonValidator>();
// etc
}
Note that the AddFluentValidationClientsideAdapters method is only available in FluentValidation 11.1 and newer. In older versions,
you should use the AddFluentValidation method which enables both
auto-validation and clientside adapters. If you only want clientside
adapters and don't want auto validation in 11.0 and older, you can
configure this by calling services.AddFluentValidation(config => config.AutomaticValidationEnabled = false)
Alternatively, instead of using client-side validation you could
instead execute your full server-side rules via AJAX using a library
such as FormHelper. This allows you to use the full power of
FluentValidation, while still having a responsive user experience.
Specifying a RuleSet for client-side messages
If you're using rulesets alongside ASP.NET MVC, then you'll notice
that by default FluentValidation will only generate client-side error
messages for rules not part of any ruleset. You can instead specify
that FluentValidation should generate clientside rules from a
particular ruleset by attributing your controller action with a
RuleSetForClientSideMessagesAttribute:
[RuleSetForClientSideMessages("MyRuleset")]
public ActionResult Index(){ return View(new Person()); }
You can also use the SetRulesetForClientsideMessages extension method
within your controller action, which has the same affect:
public ActionResult Index()
{
ControllerContext.SetRulesetForClientsideMessages("MyRuleset");
return View(new Person());
}
You can force all rules to be used to generate client-side error
message by specifying a ruleset of "*".
Read more
Read more at:
GitHub
Documentation
Was able to figure it out.
this needs to be added under, Startup file, .AddMvc().AddFluentValidation()
So, it automatically able to pick the validation at client side as well as server side.
Thanks.
You need to add .AddFluentValidation() after .AddMvc() (or .AddControllersWithViews()) to enable Fluent Validation.
Fluent Validation supports some basic client-side validations like required, maxlength etc. If you want to use all server-side validations on client-side, you need to use third party libraries like FormHelper.
Form Helper helps you to create ajax forms and validations without writing any javascript code. It transforms server-side validations to client-side. It's very to use just add .AddFormHelper() and .UseFormHelper() on Startup.cs.
FormHelper: https://nuget.org/packages/FormHelper
Document: https://github.com/sinanbozkus/formhelper
I need to write a RESTful WCF service that maintains a dictionary (or any other suitable data structure) with userId:userData as key:value pairs.
For that I first need to implement an interface for getting and setting userData (the specific configuration is enclosed):
GetConfiguration() : returns default config when user hasn’t set a config yet
GetConfiguration(string id)
SetConfiguration(string id, Configuration configurationSchema)
Then I'll need to write a service that implements this interface.
As a newbie in WCF I'm not sure how to do it. I tried to look for relevant references but didn't found any.
Appreciate any help/relevant references, Thanks !
The userData object:
public class ConfigurationSchema
{
public string MobileNumber { get; set; }
public List<string> Habits { get; set; }
public ConfigurationSchema(string mobileNumber, List<string> habits)
{
this.MobileNumber = mobileNumber;
this.Habits = habits;
}
}
may be below video will help you to create a WCF service. Once create simple WCF service after that add your code.
https://www.youtube.com/watch?v=GzN1vHWlJjA
If you did not find references to help you, I'd suggest you learn to google before you tackle programming problems. It's worth it. For your problem:
Open Visual Studio
Chose WCF project
Replace example complex data structure by your own class
Rename methods
Rename interface
Press F5
How does one configure a Remote validator via data annotations to make its call at /api/{controller} instead of /{controller}/{action}?
My model:
public class MyModel
{
[Required]
public string Name { get; set; }
[EmailAddress(ErrorMessage="We need a valid email."), Remote(....)]
public string Email { get; set; }
}
No matter what I try, the URL called by that remote validator is /foo/bar instead of just doing a get to /api/foo.
Is there any support for WebAPI in remote validators?
I'd like my email uniqueness check to use the .NET validators if at all possible (rather than having to do it manually), my form is submitted via AJAX, I'd like to validate the email prior to form submission, and using a remote validator pointing at an API controller seems like a natural choice.
Cannot use a Web API controller. This is a limitation of the RemoteAttribute. To avoid conflicts with MVC controllers, to match a Web API route you must include an httproute key, which RemoteAttribute doesn't do.
You should be able to inherit RemoteAttribute and override GetUrl to make it work.
Assuming a ApiController with an action having multiple arguments:
[HttpPost]
public void AddAddress( Person person, Address address, int simple )
Or something like that.
Now I try to send a post request with content type application/json and json like this:
{
person: {...}, address: {..}, simple: 1
}
just assume it's valid json ;)
or in a json array like this:
[person, address, simple]
But WebApi won't recognize this and tell me it can't find the action, as it doesn't support multiple parameters in a json request.
I'm doing this from a C# client using HttpClient and we'd like to do post requests using json. I wanted to use the WebApi.Client package, which provides several useful extensions to the HttpClient, but we have a portable library project(which webapi client doesn't support).
How would I go about supporting this feature?
I tried to use an custom ActionFilter, which never get's to run as it can't find the action beforehand. I tried MediaTypeFormatter which doesn't know the context and the arguments, and also I tried ModelBinder, which also seems only on a per argument basis and doesn't always get executed.
Thanks!
The built-in parameter binding strategy in ASP.NET Web API with formatters only supports a single complex argument mapped to the request body. In your case, you are trying to map at least two complex arguments. The simplest solution without extending this infrastructure would be to create a new model class containing those arguments as properties
public class AddressModel
{
public Person Person { get; set; }
public Address Address { get; set; }
public int Simple { get; set; }
}
And use that model in your controller action
public void AddAddress( AddressModel model );
if you have an entity which is reference in the client and a webservice like this
public class Post
{
public int ID {get; set;}
string Data {get; set;}
}
public class MyService: System.Web.Services.WebService
{
[WebMethod]
public int Write (Post post)
{
//Do stuff
}
}
on the client in order to use the entity you to instantiate from the proxy class
public void ClientMethod()
{
var post = new proxyclass.Post();
//fill post
new ProxyClass.Myservice().Write(post)
}
how can i use my domain entity to call the webservice?
public void ClientMethod()
{
var post = new Post();
//fill post
new ProxyClass.Myservice().Write(post)
}
Basically, you can't - with regular web-services, at least... the proxy class is completely separate. However, the above is possible with WCF, where you don't actually need proxy classes at all (however, for SOA purity it is a good idea to use them).
You could use reflection (etc) to copy the properties between your domain entities and the proxies, but it is quite hard to get this 100% right (although xml serialization should work [in theory] as an intermediate language).
So; if you want to use assembly sharing; consider using WCF, which supports this ;-p
To get hold of a service without using a proxy layer, you can do tricks like:
public class WcfClient<T> : ClientBase<T> where T : class
{
public T Service { get { return base.Channel; } }
}
(this will access the default configuration from the app.config; for more control you need to add a few constructor overloads matching to the base constructor overloads)
Then:
interface IFoo {void Bar();}
...
using(WcfClient<IFoo> client = new WcfClient<IFoo>()) {
client.Service.Bar();
}
I suspect that one of these might answer your qestion. The common theme is wsdl.exe /sharetypes and svcutil /reference.
Managing 2 web references with shared class dependency in a .NET project
Force .NET webservice to use local object class, not proxy class
.Net Consuming Web Service: Identical types in two different services
How to get a webserice to serialize/deserialize the same type in .net
.NET SOAP Common types
wsdl.exe /sharetypes
You should use WCF for new development whenever possible.
However, you should reconsider your reasons for wanting to use your domain class on the client. It does violate the principles of SOA by exposing to the client some details of the implementation of the service. Why should the client know anything about your entity classes, beyond the data that they contain?
For instance, your entity classes may contain methods to save the entity to the database. Why does your client need access to that method?
Also, one of the principals of SOA is to interoperate with different platforms. As soon as you require your client to use your (.NET) entity, you prevent a Java or PHP client from being written to use your service.
You may have good enough reasons to overcome such objections, but I recommend that you think it through and make sure your reasons are good enough.
For cases like this you're better to use json for sending and receiving data to and from web service.
Newtonsoft.json is the best json serializer for .Net. so you should change your Write method like below:
public void ClientMethod()
{
var post = new Post();
//fill post
new ProxyClass.Myservice().Write(JsonConvert.SerializeObject(post))
}