Pass Query String parameter to JsonResult action in MVC controller - asp.net-mvc

I have trying to pass a query string parameter to my JsonResult action in the controller. I keep getting the following error:
Value cannot be null.
Parameter name: String
I need the task_id from this url:
TaskIn?task_id=33
In my view I have tried (fails with same error):
#model TaskingSystem.Models.AcceptTasksViewModel
#{string task_id = #Request.QueryString["task_id"];}
#Html.HiddenFor(m => m.task_id)
In controller:
public JsonResult TasksExist(string email, string task_id)
{
int tasks_id = int.Parse("task_id");
return Json(db.Tasks_Validate.Any(e => e.Email == email && e.task_id == tasks_id), JsonRequestBehavior.AllowGet);
}
My model:
public class AcceptTasksViewModel{
[Required]
[DataType(DataType.EmailAddress)]
[Display(Name = "Email:")]
//Using Remote validation attribute
[Remote("TasksExist", "Task_Results", ErrorMessage = "Email does not exists in database. Please try a different email address.")]
public string email { get; set; }
public int task_id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
I have also tried just passing straight into the action using this but it still fails.
int tasks_id = int.Parse(Request.Params["task_id"]);

To pass the task_id along with the email to your TasksExist(string email, string task_id) method, you have to mention task_id in AdditionalFields property of Remote attribute as follows:
[Remote("TasksExist", "Task_Results",AdditionalFields = "task_id" ErrorMessage = "Email does not exists in database. Please try a different email address.")]
public string email { get; set; }

Related

c# mvc and EF - valid model returns as invalid

I have a form which I want to submit and save the data using EF, but even if all the fields are filled out correctly upon submission it still enters the invalid conditional. I think it has something to do with Id column which it shows as 0 when other fields are filled out.
Pages Data Model:
public class PagesVM
{
public PagesVM()
{
}
public PagesVM(PagesDTO pagesDTO)
{
Id = pagesDTO.Id;
Title = pagesDTO.Title;
Slug = pagesDTO.Slug;
Body = pagesDTO.Body;
}
public int Id { get; set; }
[Required]
[StringLength(50, MinimumLength = 3)]
public string Title { get; set; }
[Required]
[StringLength(50, MinimumLength = 3)]
public string Slug { get; set; }
[Required]
[StringLength(100, MinimumLength = 3)]
public string Body { get; set; }
}
Post action:
[HttpPost]
[ActionName("add-page")]
public ActionResult AddPage(PagesVM pagesVM)
{
if (! ModelState.IsValid)
{
return View("AddPage", pagesVM);
}
using (Db db = new Db())
{
PagesDTO pagesDTO = new PagesDTO();
pagesDTO.Title = pagesVM.Title;
pagesDTO.Slug = pagesVM.Slug;
pagesDTO.Body = pagesVM.Body;
db.SaveChanges();
}
ViewBag.SM = "You have added a new page!";
return View("AddPage");
}
So regardless if the form is filled out properly it goes into if (! ModelState.IsValid) always.
If Id is not set yet you would need to change
public int Id { get; set; }
to
public int? Id {get;set;}
for the model to accurately represent the data and pass validation.
If it is always set before this view and not coming through you need to put it in a
#Html.HiddenFor(x => x.Id)
inside the form tags

Remote validation not working for MVC

I have made a remote validation in my project, to avoid duplicate entries in DB. My model class is like this
public class Supplier
{
public int SupplierId { get; set; }
public string SupplierName { get; set; }
[Required, DisplayName("Supplier Code")]
[Remote("ViCodeExists", "Supplier", "Vi Code is already exists.", AdditionalFields = "SupplierId")]
public string SupplierCode { get; set; }
}
And inside my SupplierController I have the function like this
public JsonResult ViCodeExists(string SupplierCode, int SupplierId = 0)
{
var user = _db.Suppliers.Where(x => x.SupplierCode == SupplierCode.Trim() && x.SupplierId != SupplierId);
return !user.Any() ?
Json(true, JsonRequestBehavior.AllowGet) :
Json(string.Format("{0} is already exists.", SupplierCode),
JsonRequestBehavior.AllowGet);
}
In my create View
#Html.TextBoxFor(model => model.SupplierCode)
#Html.ValidationMessageFor(model => model.SupplierCode)
Everything looks okay to me, but this validation does not works. I have tried adding breakpoint inside controller, But it never get hit. Can any one point out What I am doing wrong here?
Note: I have same type of validation in some other controllers in the
same project and they all work well. Issue is with this one only.
You using the overload of RemoteAttribute that accepts 3 string parameters where the 3rd parameter is the area name (not an error message).
Change the attribute to
[Remote("ViCodeExists", "Supplier", ErrorMessage = "Vi Code is already exists.", AdditionalFields = "SupplierId")]
public string SupplierCode { get; set; }
Note your overriding the error message in the methods return statement anyway, so you can probably omit it and just use
[Remote("ViCodeExists", "Supplier", AdditionalFields = "SupplierId")]
public string SupplierCode { get; set; }

MVC Validation with Entity Framework

I'm having trouble getting validation to work on my MVC page when using Entity Framework. If someone could point out what I'm doing wrong I would appreciate it. It is definitely seeing the meta data because the labels are working. However, when I hit submit, it just continues on to the next page. Could it have something to do with the fact that I have an instance of a class inside the view model?
Meta Data Class
[MetadataType(typeof(CompanyMetaData))]
public partial class Company
{
}
[MetadataType(typeof(CompanyUserMetaData))]
public partial class CompanyUser
{
}
public class CompanyMetaData
{
[Required(ErrorMessage = "Company Name is required")]
public string Name { get; set; }
[Required(ErrorMessage = "Service Center is required")]
public string ServiceCenterCode { get; set; }
[Required(ErrorMessage = "Account Number is required")]
public string AccountNumber { get; set; }
[Required(ErrorMessage = "Edition is required")]
public string Edition { get; set; }
}
public class CompanyUserMetaData
{
[Required]
[RegularExpression(#"^\w+#[a-zA-Z_]+?\.[a-zA-Z]{2,3}$", ErrorMessage = "Invalid Email Address")]
public string EmailAddress { get; set; }
[Required(ErrorMessage = "Password is required")]
public string Password { get; set; }
[Required(ErrorMessage = "First Name is required")]
public string FirstName { get; set; }
[DisplayName("Last Name")]
[Required(ErrorMessage = "Last Name is required")]
public string LastName { get; set; }
}
View Model
public class CreateCompanyViewModel : ILayoutAwareViewModel
{
public List<AdvisorServiceCenterVW> ServiceCenters { get; set; }
public LayoutViewModel LayoutViewModel { get; set; }
public Company newCompany { get; set; }
public CompanyUser newUser { get; set; }
public List<FuneralHome> newFuneralHomes { get; set; }
}
Markup Sample
<div class="form-group">
<label>#Html.LabelFor(d=>d.newUser.LastName)</label>
<div class="controls">
#Html.TextBoxFor(d => d.newUser.LastName, new { #class = "form-control" })
#Html.ValidationMessageFor(d => d.newUser.LastName)
</div>
</div>
Controller
public ActionResult CreateCompanyLocations(CreateCompanyViewModel incomingModel)
{
var model = (CreateCompanyViewModel)TempData["model"];
LayoutViewModel lvm = _layoutHelper.GetLayoutViewModelData("Configure New Company");
model.LayoutViewModel = lvm;
model.newCompany = incomingModel.newCompany;
model.newUser = incomingModel.newUser;
var fhs = _siteService.GetCustomerLocations(model.newCompany.AccountNumber);
model.newFuneralHomes = new List<FuneralHome>();
foreach (var fh in fhs)
{
model.newFuneralHomes.Add(new FuneralHome()
{
Address = fh.Address,
Name = fh.CustomerName,
City = fh.City,
AccountNumber = fh.AccountNumber,
ServiceCenterCode = fh.ServiceCenterCode,
State = fh.State,
ZipCode = fh.ZipCode,
Phone = fh.Phone,
ContactName = fh.ContactName
});
}
TempData["model"] = model;
return View(model);
}
You need to check ModelState.IsValid in your controller code and branch accordingly. Currently your controller is just processing the model whether it is valid or not. The typical pattern looks something like this:
if(ModelState.IsValid)
{
// Do stuff for when model is valid
}
else
{
// return the view with the invalid model to give the user
// a chance to fix it
return View(model);
}
It wound up having nothing to do with the above answer. I was missing the jquery validation and jquery unobtrusive scripts on my layout page so that is what was causing the validation not to fire. You do NOT need to do anything in the controller for this to work correctly.

How to read properties when POST but JsonIgnore GET in Json .NET Web API

I'm trying to make Json .NET Ignore a property by using the Json Ignore Attribute when clients GET the object but I want to be able to receive that property when a client is POST'ing
In example I have:
When the client POSTs data, password should be sent:
{"email":"email#domain.com","password":"P#ssW0rd1!","firstname":"Joe","lastname":"Doe"}
However, when the client GETs the same object, I should Ignore the Password:
{"email":"email#domain.com","firstname":"Joe","lastname":"Doe"}
Class:
public class User
{
public User()
{
this.JoinDate = DateTime.UtcNow;
this.IsActive = false;
}
public int Id { get; set; }
[Required(ErrorMessage = "Email is required!")]
public string Email { get; set; }
[JsonIgnore]
public string HashedPassword { get; set; }
[Required(ErrorMessage = "Password is required!")]
public string Password { get; set; }
public DateTime JoinDate { get; set; }
[Required(ErrorMessage = "First Name is required!")]
public string FirstName { get; set; }
[Required(ErrorMessage = "Last Name is required!")]
public string LastName { get; set; }
}
Any ideas, suggestions, comments???
In your scenario here, I would recommend you to split your User class into 2 separate model classes:
Login class, which has the login information (i.e. Email, Password)
UserInfo class, which has the rest of the metadata about the User (i.e. FirstName, LastName)
This way, we are not depending on the serializer to hide sensitive data.
You could use [IgnoreDataMember] attributes and the out-of-box XML and JSON formatters will support them, but there is no guarantee that any other custom formatter registered will support it.
Note that [JsonIgnore] is only supported in the JSON formatter but not the XML formatter.

MVC Remote Validation accessing field from class above

In the below code I cannot pass the username to the remote validation function:
public string UserName { get; set; }
public class Numbers
{
[Display(Name = "Additonal Numbers")]
[Remote("NumberExists", "Account", AdditionalFields = "UserName", ErrorMessage = "Serial is already taken.")]
public string additionalNumbers { get; set; }
}
public List<Numbers> NumberList { get; set; }
This is a simple example but I would like to pass additional fields from the same model within a list but I cant seem to access anything outside the scope of the public class.
Do I need to pass the rest of the model into the list in some way to achieve this or am I doing something wrong here?
The AdditionalFields parameter in the remote validation attribute need to be in the same class as the object being validated.
..edit..
public class Numbers
{
public string UserName { get; set; }
[Display(Name = "Additonal Numbers")]
[Remote("NumberExists", "Account", AdditionalFields = "UserName", ErrorMessage = "Serial is already taken.")]
public string additionalNumbers { get; set; }
}
..edit after comments..
It looks like what you want to do is validate that all the numbers are unique for a Username. Try this:
public string UserName { get; set; }
[Display(Name = "Additonal Numbers")]
[Remote("NumberExists", "Account", AdditionalFields = "UserName", ErrorMessage = "Serial is already taken.")]
public List<String> NumberList { get; set; }
In your NumberExists Action take a List of Strings rather than only 1 string. This will let you validate your whole array all at once.
Public ActionResult NumberExists(List<String> NumberList, String UserName){
//Validate list is unique for username
}
UserName Property should be in the same class of the additionalNumbers property:
public class NumbersViewModel
{
public string UserName { get; set; }
[Display(Name = "Additonal Numbers")]
[Remote("NumberExists", "Account", AdditionalFields = "UserName", ErrorMessage = "Serial is already taken.")]
public string additionalNumbers { get; set; }
public List<Numbers> NumberList { get; set; }
}

Resources