Asp.net mvc connect to webApi by httpClient - asp.net-mvc

I have mvc application and webApi application. I need sign in in asp.net mvc through webApi. When i use this method:
public static string GetToken(LoginModelView login)
{
var pairs = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>( "grant_type", "password" ),
new KeyValuePair<string, string>( "username", login.Login ),
new KeyValuePair<string, string> ( "Password", login.Password )
};
var content = new FormUrlEncodedContent(pairs);
using (var client = new HttpClient())
{
var response =
client.PostAsync(URL + "/Token", content).Result;
var responseJson = response.Content.ReadAsStringAsync().Result;
var dictionaryToken = JsonConvert.DeserializeObject<Dictionary<string,string>>(responseJson);
string token = dictionaryToken["access_token"];
return token;
}
}
My mvc don't bind model from view.
Action methods
[HttpGet]
public ActionResult SignIn()
{
var login = new LoginModelView();
return View("SignIn",login);
}
[HttpPost]
public ActionResult SignIn(LoginModelView login)
{
string token = DirService.GetToken(login);
Session["token"] = token;
return RedirectToAction("success");
}
It's model
public class LoginModelView
{
public string Login { get; set; }
public string Password { get; set; }
}
It's my view
#model AdminTool.Models.LoginModelView
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>LoginModelView</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Login, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Login, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Login, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Password, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Password, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Password, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Login" class="btn btn-default" />
</div>
</div>
</div>
}
when i don't use that method, everything is ok.
The same code works in another application.
Somebody can help me, please..

I noticed that in LoginModelView class has Login Property and you create same object name LoginModelView login in controller.I change that code and its Work For Me.
Model:-
[HttpGet]
public ActionResult SignIn()
{
var loginModelView = new LoginModelView();
return View("SignIn", loginModelView);
}
[HttpPost]
public ActionResult SignIn(LoginModelView loginModelView)
{
string token = DirService.GetToken(loginModelView);
Session["token"] = token;
return RedirectToAction("success");
}
Hope Its Work !!!
Happy Coding !!

I think you posting from data to get method(GetToken).

Related

Another [Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'Cannot perform runtime binding on a null reference'] in ASP.NET MVC

I tried to have a file upload into another folder, it works fine when it directly add to the database, but if I try to use it with MultipleDocumentCreateClass for the stored procedure, I get this error:
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'Cannot perform runtime binding on a null reference'
Controller
// GET: Activity/DocumentNew
public ActionResult DocumentNew(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Hoạt_động hoạt_động = db.Hoạt_động.Find(id); ;
ViewBag.act = hoạt_động;
if (hoạt_động == null)
{
return HttpNotFound();
}
MultipleDocumentCreateClass mtd = new MultipleDocumentCreateClass();
mtd.Mã_Hoạt_động = hoạt_động.Mã_Hoạt_động;
Dropdownlist2();
return View(mtd);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult DocumentNew([Bind(Include = "Mã_Hoạt_động, Tên, Loại,Thông_tin, Nội_dung")]MultipleDocumentCreateClass mt)
{
if (ModelState.IsValid)
{
if (Request.Files.Count > 0)
{
HttpPostedFileBase file = Request.Files[0];
if (file.ContentLength > 0)
{
var fileName = Path.GetFileName(file.FileName);
//Save into folder
file.SaveAs(Server.MapPath("/App_Data/Video/" + fileName));
mt.Nội_dung = "~/App_Data/Video/" + fileName;
mt.Tên = Path.GetFileNameWithoutExtension(file.FileName);
}
db.MultipleDocCr(mt.Mã_Hoạt_động, mt.Tên, mt.Loại, mt.Thông_tin, mt.Nội_dung);
db.SaveChanges();
return RedirectToAction("Index");
}
}
return View(mt);
}
MultipleDocumentUseClass:
public class MultipleDocumentCreateClass
{
public Nullable<int> Mã_Hoạt_động { get; set; }
public string Tên { get; set; }
public string Loại { get; set; }
public string Thông_tin { get; set; }
public string Nội_dung { get; set; }
}
View
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Hoạt động: #Model.Mã_Hoạt_động</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.Mã_Hoạt_động, new { value = ViewBag.act.Mã_Hoạt_động })
<dt>
Hoạt động:
#ViewBag.act.Tên
</dt>
<div class="form-group">
#Html.LabelFor(model => model.Loại, "Thể loại", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.Loại, new SelectList(ViewBag.doc, "Value", "Text"), new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.Loại, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Thông_tin, "Thông tin", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Thông_tin, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Thông_tin, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Nội_dung, "Chọn File", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Nội_dung, new { htmlAttributes = new { Type = "file" } })
#Html.ValidationMessageFor(model => model.Nội_dung, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Lưu" class="btn btn-default" />
</div>
</div>
</div>
}
The error points to this line
#Html.HiddenFor(model => model.Mã_Hoạt_động, new { value = ViewBag.act.Mã_Hoạt_động })
but when I add value manually without uploading, it works fine.
So the answer at the #using (Html.BeginForm()) in View
Change it into this #using (Html.BeginForm("DocumentNew", "Activity", FormMethod.Post, new { enctype = "multipart/form-data" }))

Deserializing current JSON Array to perform edit operation using web api

I am using web API to edit values from collection in MongoDB.I have added code to fetch values from mongodb and have called it in another to fetch the api to perform edit functionality.
My id is getting passed to the action and still null refernce exception occur when i fix it deserialize array error occur. I tried to put deserialize the array using code found in net but it didnt work! Why does this error occur? I am new in web api and mongo db !! Please help!
Contact.cs(Model class)
public class Contact
{
[BsonId]
public string Id { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
}
mongodbcontroller(Controller)
[System.Web.Http.HttpPut]
public Contact Edit(Contact contact)
{
var contactsList = mongoDatabase.GetCollection("contact");
WriteConcernResult result;
bool hasError = false;
string errorMessage = string.Empty;
try
{
if (!string.IsNullOrEmpty(contact.Id))
{
IMongoQuery query = Query.EQ("Id", contact.Id);
IMongoUpdate update = MongoDB.Driver.Builders.Update
//.Set("Id",contact.Id)
.Set("Name", contact.Name)
.Set("Address", contact.Address)
.Set("Phone", contact.Phone)
.Set("Email", contact.Email);
result = contactsList.Update(query, update);
contactsList.Save(contact);
hasError = result.HasLastErrorMessage;
}
}
catch(Exception ex)
{
errorMessage = ex.ToString();
}
if (!hasError)
{
return contact;
}
else
{
throw new HttpResponseException(HttpStatusCode.InternalServerError);
}
}
TestController(Consuming the api)
public ActionResult Edit(string id)
{
//Contact contact = new Contact();
Contact contact = new Contact();
try
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:61093/api/MongoDb/edit");
//HTTP GET
var responseTask = client.GetAsync("?id=" + id);
responseTask.Wait();
var result = responseTask.Result;
if (result.IsSuccessStatusCode)
{
var readTask = result.Content.ReadAsAsync<Contact>();
readTask.Wait();
contact = readTask.Result;
}
}
}
catch (Exception ex)
{
}
return View(contact);
}
[HttpPost]
public ActionResult Edit(Contact contact)
{
try
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:61093/api/MongoDb/edit");
//HTTP GET
var putTask = client.PutAsJsonAsync<Contact>("contact",contact);
putTask.Wait();
var result = putTask.Result;
if (result.IsSuccessStatusCode)
{
return RedirectToAction("Index");
}
}
}
catch (Exception ex)
{
}
return View(contact);
}
Edit.cshtml(View)
#model TestApi.Models.Contact
#{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Contact</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.Id)
<div class="form-group">
#Html.LabelFor(model => model.Name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Name, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Name, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Address, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Address, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Address, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Email, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Email, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Email, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Phone, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Phone, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Phone, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Screenshots of my code is attched below

Form Submit Not Work in MVC 5 Project

My Submit Form Button Not Working ..
When I press on Login Button Nothing Happens ...
I had set breakpoint in my code and Login Post Action not Called after Submit Button Click .
I can fix my problem with JQuery ajax codes but I don't want use JQuery Ajax for submitting Form ..I want to understand and resolve this MVC problem
thank you ...
User Model :
namespace Models
{
public class User : BaseEntity
{
public User() : base()
{
}
[System.ComponentModel.DataAnnotations.Required]
public string Username { get; set; }
[System.ComponentModel.DataAnnotations.Required]
[System.ComponentModel.DataAnnotations.DataType(System.ComponentModel.DataAnnotations.DataType.Password)]
public string Password { get; set; }
}
}
BaseEntity Class has only Id (System.Guid) Property
Controller :
public class AdminController : Infrastructure.BaseController
{
[System.Web.Mvc.HttpGet]
public System.Web.Mvc.ActionResult Index()
{
return View();
}
[System.Web.Mvc.HttpGet]
public System.Web.Mvc.ActionResult Login()
{
return View();
}
[System.Web.Mvc.HttpGet]
public System.Web.Mvc.ActionResult Edit()
{
return View();
}
[System.Web.Mvc.HttpPost]
[System.Web.Mvc.ValidateAntiForgeryToken]
public System.Web.Mvc.ActionResult Login([System.Web.Mvc.Bind(Include = "Id,Username,Password")] Models.User user)
{
string password = AAk.Security.Hashing.GetMD5(user.Password);
Models.User oUser = MyDatabaseContext.Users
.Where(current => current.Username.Contains(user.Username))
.Where(current => current.Password == password)
.FirstOrDefault();
if(oUser != null)
{
System.Web.Security.FormsAuthentication.SetAuthCookie(user.Username, false);
Session["AdminUserId"] = user.Id;
return (RedirectToAction("Edit", "Admin"));
}
else
{
//ModelState.AddModelError(string.Empty, "Login Failed!");
PageMessages.Add(new Infrastructure.PageMessage(Infrastructure.PageMessage.Types.Error, "Login Failed!"));
}
return (View(model: user));
}
}
Login.cshtml
#model Models.User
#{
ViewBag.Title = "Login";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Login</h2>
#using (Html.BeginForm("Login", "Admin", FormMethod.Post))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.Partial(partialViewName: "~/Views/Shared/_PageMessages.cshtml")
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.Id)
<div class="form-group">
#Html.LabelFor(model => model.Username, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Username, new { htmlAttributes = new { #class = "form-control", #id = "username" } })
#Html.ValidationMessageFor(model => model.Username, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Password, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Password, new { htmlAttributes = new { #class = "form-control", #id = "password" } })
#Html.ValidationMessageFor(model => model.Password, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Login" class="btn btn-default" id="login-button" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>

ASP.NET MVC - Null Object in ViewModel on POST

Upon POST of an ActionController I am receiving the great ole' object reference not set to an instance of an object error.
Basically I need the ID of the userRequest to be saved WITH the requestResponse. (Foreign Key here)
Here is the code.
ViewModel:
public class RequestResponseViewModel
{
public Models.Request userRequest { get; set; }
public Models.RequestResponse requestResponse { get; set; }
}
View: In debug here there is value in model.userRequest.ID
#model UserRequests.ViewModels.RequestResponseViewModel
#{
ViewBag.Title = "Create";
}
<h2>Admin Response to Request</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.requestResponse.Response,
htmlAttributes: new { #class = "control-label col-md-1" })
<div class="col-md-10">
#Html.TextAreaFor(model => model.requestResponse.Response, new {
#class = "form-control", #rows = 5 })
#Html.ValidationMessageFor(model =>
model.requestResponse.Response, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.userRequest.ID, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-2">
#Html.DisplayFor(model => model.userRequest.ID)
#Html.ValidationMessageFor(model => model.userRequest.ID, "", new { #class = "text-danger" })
</div>
#Html.LabelFor(model => model.requestResponse.Author, htmlAttributes: new { #class = "control-label col-md-1" })
<div class="col-md-3">
#Html.EditorFor(model => model.requestResponse.Author, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.requestResponse.Author, "", new { #class = "text-danger" })
</div>
#Html.LabelFor(model => model.requestResponse.CreateDate, htmlAttributes: new { #class = "control-label col-md-1" })
<div class="col-md-3">
<h5>#DateTime.Now</h5>
#Html.ValidationMessageFor(model => model.requestResponse.CreateDate, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-1">
<button type="reset" class="btn btn-default">Cancel</button>
<input type="submit" value="Create" class="btn btn-success" />
</div>
</div>
</div>
<hr />
<h3 class="text-success">Original Request</h3>
<div class="row">
<div class="col-md-10">
<h4>#Html.DisplayFor(model => model.userRequest.Title)</h4>
</div>
</div>
<div class="row">
<div class="col-md-10">
<h4>#Html.DisplayFor(model => model.userRequest.Description)</h4>
</div>
</div>
}
<div>
#Html.ActionLink("Back to Browse", "Browse","Change")
</div>
Get ActionResult:
public ActionResult Create(int id)
{
UserRequestContextDataContext db = new UserRequestContextDataContext();
var request = (from m in db.Requests
where m.ID == id
select new Models.Request()
{
ID = m.ID,
Title = m.Title,
Description = m.Description,
BusinessUnit = m.BusinessUnit,
Author = m.Author,
ModuleName = m.MenuItem,
RequestStatus = 2,
SubmitDate = m.SubmitDate,
Type = m.Type,
UrgencyNum = m.UrgencyLevel
}).FirstOrDefault();
var reqResponse = new Models.RequestResponse();
var viewModel = new RequestResponseViewModel
{
userRequest = request,
requestResponse = reqResponse
};
return View(viewModel);
}
The "viewModel" here has everything I need. It's lost somewhere between the ActionResults..
And Finally the Post ActionResult:
[HttpPost]
public ActionResult Create(RequestResponseViewModel _requestResponseViewModel)
{
try
{
if (ModelState.IsValid)
{
using (UserRequestContextDataContext db = new UserRequestContextDataContext())
{
RequestResponse reqRes = new RequestResponse();
reqRes.Response = _requestResponseViewModel.requestResponse.Response.ToString();
reqRes.RequestID = _requestResponseViewModel.userRequest.ID;
reqRes.Author = _requestResponseViewModel.requestResponse.Author.ToString();
reqRes.CreateDate = DateTime.Now;
db.RequestResponses.InsertOnSubmit(reqRes);
db.SubmitChanges();
}
}
return RedirectToAction("Browse","Change");
}
catch (Exception ex)
{
return View("Error", new HandleErrorInfo(ex, "Change", "Create"));
}
}
Using debug mode the userRequest object is NULL in the view model parameter of the POST method but requestResponse is FINE and populated as should.
Searching on this, it seemed most had issues with the naming convention in the view model but I've made sure there are no discrepancies there.
If there is a more clear way to do this workflow please mention.
#Html.DisplayFor does not create an HTML input element, but a simple string literal (for most types, some exceptions are listed in the docs: https://msdn.microsoft.com/en-us/library/ee407420(v=vs.118).aspx#Anchor_1).
So when you press submit, your browser will not send the ID back to the server because it sends only form data (e.g. data from input, textare, select fields). Using your browsers developer tools (F12) you can examine what is actually send to the server.
You can add a hidden input field using #Html.HiddenFor(model => model.userRequest.ID) or use a custom display template for the ID to automatically add a hidden input field. You could further use UIHint attributes to automatically select a display template. Both approaches are thoroughly documented (e.g. http://www.codeguru.com/csharp/.net/net_asp/mvc/using-display-templates-and-editor-templates-in-asp.net-mvc.htm).
Another reason the object could be NULL in the POST is due to forgetting to add the setters { get; set; } in your view model:
public Orders orders; --> missing { get; set; }
public class OrderViewModel
{
public Orders orders { get; set; }
public List<VendorJobTitleView> Jobs { get; set; }
public List<ManagerView> Managers { get; set; }
}

MVC Unobtrusive custom rule only works in one form on client

I built a custom validation rule for one particular field on my MVC 5 app. It works great on the edit form, but when validating that same field on the "create' form, the client side validation does not fire - The client side validation is triggered, but on the create form it shows as valid, even though I can see it is not. So no message is shown.
Both forms use the same model.
The scripts are added in the _layout page so both views have all the scripts.
Both views have the exact same razor code including the ValidationMessageFor()
When the form gets to the controller, the model is not valid due to the custom error. So the validation is working on the server side, but not the client. I can't find anything that would make it work in one form but not the other.
Here is my code:
Custom attribute:
public class AtLeastOneRequiredAttribute : ValidationAttribute, IClientValidatable
{
public string OtherPropertyNames;
public AtLeastOneRequiredAttribute(string otherPropertyNames)
{
OtherPropertyNames = otherPropertyNames;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
string[] propertyNames = OtherPropertyNames.Split(',');
bool IsAllNull = true;
foreach(var i in propertyNames)
{
var p = validationContext.ObjectType.GetProperty(i);
var val = p.GetValue(validationContext.ObjectInstance, null);
if(val != null && val.ToString().Trim() != "")
{
IsAllNull = false;
break;
}
}
if(IsAllNull)
{
return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
}
else
{
return null;
}
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var rules = new ModelClientValidationRule()
{
ErrorMessage = FormatErrorMessage(metadata.DisplayName),
ValidationType = "atleastonerequired"
};
rules.ValidationParameters["otherpropertynames"] = OtherPropertyNames;
yield return rules;
}
}
Client code:
$(function() {
$.validator.unobtrusive.adapters.addSingleVal("atleastonerequired", "otherpropertynames");
$.validator.addMethod("atleastonerequired", function (value, element, params) {
var param = params.toString().split(',');
var IsAllNull = true;
$.each(param, function (i, val) {
var valueOfItem = $('#Activity_' + val).val().trim();
if (valueOfItem != '') {
IsAllNull = false;
return false;
}
});
if (IsAllNull) {
return false;
}
else {
return true;
}
})
})
View - Edit & Create Forms are identical:
#using (Html.BeginForm("Edit", "Activity", FormMethod.Post, new { #id = "editActivityForm" }))
{
#Html.AntiForgeryToken()
<div class="form activity-form">
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.Activity.RecordId)
<div class="form-group">
#Html.LabelFor(model => model.Activity.Acres, htmlAttributes: new { #class = "control-label" })
#Html.EditorFor(model => model.Activity.Acres, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Activity.Acres, "", new { #class = "text-danger" })
</div>
<div class="form-group">
#Html.LabelFor(model => model.Activity.Volume, htmlAttributes: new { #class = "control-label" })
#Html.EditorFor(model => model.Activity.Volume, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Activity.Volume, "", new { #class = "text-danger" })
</div>
<div class="form-group">
#Html.LabelFor(model => model.Activity.Feet, htmlAttributes: new { #class = "control-label" })
#Html.EditorFor(model => model.Activity.Feet, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Activity.Feet, "", new { #class = "text-danger" })
</div>
<div class="form-group">
#Html.LabelFor(model => model.Activity.Hours, htmlAttributes: new { #class = "control-label" })
#Html.EditorFor(model => model.Activity.Hours, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Activity.Hours, "", new { #class = "text-danger" })
</div>
<div class="form-group">
#Html.LabelFor(model => model.Activity.Comment, htmlAttributes: new { #class = "control-label" })
#Html.EditorFor(model => model.Activity.Comment, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Activity.Comment, "", new { #class = "text-danger" })
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" onclick="$.validator.unobtrusive.parse($('#editActivityForm'));" />
</div>
</div>
}
Model with attirbute added:
[AtLeastOneRequired("Acres,Volume,Feet,Hours", ErrorMessage = "Activity requires at least one measure - Acres, Volume, Feet or Hours.")]
public Nullable<int> Acres { get; set; }
public Nullable<int> Volume { get; set; }
public Nullable<int> Feet { get; set; }
public Nullable<int> Hours { get; set; }
The problem was with the client code. I finally found the client code was not being hit. I eventually found it was because the validation add was inside (function() {}). I deleted that 'ready' piece and now it works every time.

Resources