{"id":23763963,"url":"https://github.com/tomashubelbauer/asp-conditional-validations","last_synced_at":"2026-01-28T10:03:59.636Z","repository":{"id":107985989,"uuid":"227332170","full_name":"TomasHubelbauer/asp-conditional-validations","owner":"TomasHubelbauer","description":"Shared conditional validations approach for ASP .NET Core","archived":false,"fork":false,"pushed_at":"2022-04-14T19:35:02.000Z","size":698,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-06-01T16:42:48.333Z","etag":null,"topics":["asp","asp-net","asp-net-core","fluent-validations","form-validation","validation","validations","validator"],"latest_commit_sha":null,"homepage":"","language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/TomasHubelbauer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2019-12-11T09:56:13.000Z","updated_at":"2021-04-04T15:40:03.000Z","dependencies_parsed_at":"2024-06-04T13:09:23.849Z","dependency_job_id":null,"html_url":"https://github.com/TomasHubelbauer/asp-conditional-validations","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/TomasHubelbauer/asp-conditional-validations","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TomasHubelbauer%2Fasp-conditional-validations","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TomasHubelbauer%2Fasp-conditional-validations/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TomasHubelbauer%2Fasp-conditional-validations/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TomasHubelbauer%2Fasp-conditional-validations/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TomasHubelbauer","download_url":"https://codeload.github.com/TomasHubelbauer/asp-conditional-validations/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TomasHubelbauer%2Fasp-conditional-validations/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28844011,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-28T07:39:25.367Z","status":"ssl_error","status_checked_at":"2026-01-28T07:39:24.487Z","response_time":57,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["asp","asp-net","asp-net-core","fluent-validations","form-validation","validation","validations","validator"],"created_at":"2024-12-31T22:13:58.083Z","updated_at":"2026-01-28T10:03:59.631Z","avatar_url":"https://github.com/TomasHubelbauer.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ASP .NET Core Conditional Validations\n\n[**WEB**](https://tomashubelbauer.github.io/asp-conditional-validations)\n\nHave custom `Required` attribute, which uses the validation context to decide\nwhether to apply itself or not - this is the server side validation.\n\nThe attribute would also have a property, which would be a JavaScript expression\nfor the client side and on the client side, the form elements which are created\nand have their validation attributes set by ASP .NET Core would also be\ndecorated and there would be a hook which would run the JavaScript expression so\nthat they can also conditionally disable themselves based on the same rules.\n\nA more systematic approach to this would be to not duplicate the expression,\nonce for the attribute `IsValid` override in C# and then for the client as the\nJavaScript expression property which gets passed to the client, but is semantically\nequivalent and instead have a DSL which generates the `IsValid` override logic as\nwell as the JavaScript expression for the client.\n\nIn case of the above DSL, instead of using attributes, Fluent Validation could\nalso be used and its rules configured from the declarative shared object and the\nsame object could be serialized for the client and the same object could be used\nto generate the validation rules for jQuery validator or similar.\n\nThis way the validation rules would be only in once place and would stay in sync\nacross the backend and the frontend, enabling for conditional attributes based on\ncomplex logic.\n\nWhether to keep using data annotation attributes or Fluent Validations and to use\na plain JavaScript expression, jQuery validation, Kendo validator etc. on the client\nwould be a matter of choice as a \"DSL backend\" implementation.\n\n## Example\n\nModel:\n\n```cs\nclass Model\n{\n  [Required]\n  string Title { get; set; }\n  \n  [Required]\n  string Category { get; set; }\n  \n  [RequiredIfCategory(\"category1\")]\n  string Category1Description { get; set; }\n  \n\n  [RequiredIfCategory(\"category2\")]\n  string Category2Description { get; set; }\n}\n```\n\nThis is using the data annotation attributes. `RequiredIfCategory` would be a custom\nattribute with custom `IsValid` logic which would use the validation context from the\n2nd argument to access the `Category` field on the model and either apply self or not\nbased on the field value.\n\n```cs\nclass RequiredIfCategoryAttribute: RequiredAttribute\n{\n  public RequiredIfCategoryAttribute(string category)\n  {\n  \n  }\n  \n  IsValid(object model, ValidationContext validationContext)\n  {\n    if (model.Category == _category) {\n      // Required\n    }\n    else {\n      // Not required\n    }\n  }\n}\n```\n\nhttps://stackoverflow.com/a/16100455/2715716\n\nThis takes care of the backend, but on the frontend, the form element would still have\na required HTML attribute on itself, because this attribute still derives from `Required`\nso that the ASP .NET Core validations framework would most likely still print that HTML\nattribute since this custom attribute is based on the `Required` one.\n\nTo solve the client side, we would need to distinguish form elements which have been\nmarked with the required attribute based on the `Required` framework attribute or our\ncustom attribute.\n\nIf we could do that, we could run a JavaScript expression, which would find these\nfields marked by the custom attribute and use the same logic which the attribute\nimplements on the backend side to do the same logic on the client side, resulting in\nsemantically equivalent validations on the server and on the client.\n\nOf course this would mean duplicating the validation logic in C# and JS, so ideally,\nthere could be a DSL or a declarative validation ruleset object, which would be\nexecuted by a generalized validator on both the server and the client.\n\nThis way, instead of the attribute implementing the C# logic and also accepting the\nsemantically equivalent JS expression, it would just be a generic custom attribute\naccepting this DSL ruleset and deriving the server logic from it as well as marking\nthe form element on the client so that a geenralized client side logic could go through\nthese form elements and based on the same DSL ruleset, execute a JavaScript equivalent\nof those checks.\n\nInstead of using a custom attribute, then, a custom Fluent Validations chain could be\nderived from the DSL instead and same on the client for the various client side\nvalidation libraries.\n\nhttps://fluentvalidation.net/start\n\nhttps://github.com/JeremySkinner/FluentValidation#example\n\nhttps://docs.microsoft.com/en-us/aspnet/core/mvc/models/validation\n\n## Running\n\n`dotnet run` or `dotnet watch run`\n\n## To-Do\n\n### Make `JobTitle` on `DemoModel` required if `IsEmployed` is true\n\n### Get client side validations to run with the out of the box functionality\n\nhttps://docs.microsoft.com/en-us/aspnet/core/mvc/views/working-with-forms\n\n### Set up the required attribute on the server to use the validation context\n\nApply itself or not depending on `IsEmployed`.\n\n### Generate the client side validations based on the generalized declarative model\n\n### Figure out how to distinguish form components marked by ASP .NET and custom attribute\n\nSee above.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftomashubelbauer%2Fasp-conditional-validations","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftomashubelbauer%2Fasp-conditional-validations","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftomashubelbauer%2Fasp-conditional-validations/lists"}