MVC项目发布后Custom validation attribute无法正常工作
Hey there, let's break down why your custom MVC validation attribute is misbehaving after publishing—this is a super common pain point, and I’ve sorted through similar issues a handful of times. Here are the most likely fixes to work through:
1. First Check: Client-Side Validation Setup
MVC relies on unobtrusive JS validation to trigger client-side checks, and production builds often mess this up accidentally:
- Verify script references: Make sure your layout page includes these two scripts (they’re easy to miss in minified/production bundles):
<script src="~/Scripts/jquery.validate.min.js"></script> <script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script> - Double-check Web.config settings: Ensure client validation isn’t disabled in production:
<appSettings> <add key="ClientValidationEnabled" value="true" /> <add key="UnobtrusiveJavaScriptEnabled" value="true" /> </appSettings>
2. Fix Your IsValid Method Implementation
Your code snippet cuts off the IsValid method, which is almost certainly where the issue lies. Here’s a corrected, production-safe implementation that addresses common pitfalls:
[AttributeUsage(AttributeTargets.Property)] public class TimeGreaterThanAttribute : ValidationAttribute { public string TimeToCompareToFieldName { get; } public string DayOff { get; } public TimeGreaterThanAttribute(string timeToCompareToFieldName, string dayOff) { TimeToCompareToFieldName = timeToCompareToFieldName; DayOff = dayOff; ErrorMessage = $"This time must be later than {TimeToCompareToFieldName}"; } protected override ValidationResult IsValid(object value, ValidationContext validationContext) { // Guard clause: Ensure the comparison property exists var compareProperty = validationContext.ObjectType.GetProperty(TimeToCompareToFieldName); if (compareProperty == null) { return new ValidationResult($"Property '{TimeToCompareToFieldName}' not found on model."); } // Get values and handle nulls gracefully var currentTimeValue = value as TimeSpan?; var compareTimeValue = compareProperty.GetValue(validationContext.ObjectInstance) as TimeSpan?; if (!currentTimeValue.HasValue || !compareTimeValue.HasValue) { return ValidationResult.Success; // Or return an error if nulls aren't allowed } // Skip validation if it's the specified day off if (!string.IsNullOrWhiteSpace(DayOff)) { var currentDay = DateTime.Now.DayOfWeek.ToString(); if (currentDay.Equals(DayOff, StringComparison.OrdinalIgnoreCase)) { return ValidationResult.Success; } } // Core validation logic if (currentTimeValue.Value <= compareTimeValue.Value) { return new ValidationResult(FormatErrorMessage(validationContext.DisplayName)); } return ValidationResult.Success; } }
Key fixes here:
- Added null handling for properties and values (production data is messy!)
- Made property getters public (reflection can fail with private properties in optimized builds)
- Used case-insensitive comparison for the
DayOffcheck - Properly formatted the error message using the display name
3. Rule Out Production-Specific Edge Cases
- Code obfuscation: If you’re using tools like Dotfuscator, exclude your model class and validation attribute—obfuscation breaks reflection-based logic like this.
- Culture settings: Production servers might use a different culture, leading to time parsing errors. Add
CultureInfo.InvariantCultureto any time conversion logic if you’re dealing with string inputs. - ModelState checks: Ensure your controller action actually validates the model:
[HttpPost] public ActionResult Submit(YourModel model) { if (!ModelState.IsValid) { return View(model); // This triggers server-side validation errors } // Rest of your logic }
4. Verify Deployment Files
- Check that the DLL containing your
TimeGreaterThanAttributeis present in the production server’sbinfolder. - Ensure no version mismatches exist between your development and production assemblies.
Start with these steps—9 times out of 10, the issue is either a missing client-side script, a bug in the IsValid method, or a production configuration quirk.
内容的提问来源于stack exchange,提问作者Dean

