View model absence in registration form - asp.net-mvc

I have a partial view that contains a registration form with the following fields:
E-Mail
First Name
Last Name
Password
I am posting the form using jQuery Ajax without using View Model.
Question : Is it a good approach to not use View Model in his context ?
Question : Is my approach useless in case of unit test cases?
jQuery
$.ajax({
url: "#Url.Action("Action", "Controller", new { area = "Area" })",
type: "POST",
contentType: 'application/json; charset=utf-8',
dataType: "json",
data: JSON.stringify({mail : "mails", nam : nam ......}),
traditional: true,
success: function (data) {
alert("wsaved");
}
});
[HpPost]
public Actionresult abc(string mail, string nam, sring lasnam)
{
return Json(new {succss = ru});
}

Is it a good approach to not use View Model in his context ?
No, it will make validation much harder. Suppose that you wanted to validate that the email is not empty and is indeed a valid email address. If you used a view model, all you had to do is decorate the Email property on your view model with the correct validation attributes. With your approach you will now have to write a couple of useless lines of code in your controller action for that.
Here's how your view model might look like:
public class RegisterUserViewModel
{
[Required]
[RegularExpression("PUT YOUR REGEX TO VALIDATE AN EMAIL HERE")]
public string Email { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
[Required]
[RegularExpression("PUT YOUR REGEX TO ENFORCE SOME PASSWORD STRENGTH")]
public string Password { get; set; }
}
and now your controller action becomes:
[HttpPost]
public ActionResult Register(RegisterViewModel model)
{
if (!ModelState.IsValid)
{
// validation failed
var errors = ModelState
.Where(x => x.Value.Errors.Count > 0)
.Select(x => new
{
Key = x.Key,
Errors = x.Value.Errors.Select(e => e.ErrorMessage)
}
);
return Json(new { success = false, errors = errors });
}
return Json(new { success = true });
}

IF you are using an ApiController with MVC 4, then you can use a Model to bind to, which will use (by default) Newton Json.NET.
ResponseModel
[DataContact]
public class ResponseModel
{
[DataMember]
public string Status { get; set; }
}
ActionModel
[DataContact]
public class RegisterUserViewModel
{
[Required]
[DataMember(isRequired=true)]
public string Email { get; set; }
[DataMember]
public string FirstName { get; set; }
[DataMember]
public string LastName { get; set; }
[Required]
[DataMember(isRequired="true")]
public string Password { get; set; }
}
ApiController Action
[HttpPost]
public ReponseModel Register(RegisterActionModel actionModel)
{
if (this.ModelState == valid)
{
//do stuff
return new ResponseModel()
{
Status = "OK"
};
}
else
{
return new ResponseModel()
{
Status = "Invalid Data"
}
}
}

Related

MVC route option is persisting on reload (F5) of page

I have the following server side code in place in my MVC controller, it's a basic post, get, redirect pattern using model binding.
The problem is that after I submit the page it does the RedirectToAction sending the route option bool parameter correctly. But when I then reload the page (F5) it's still sending the route option parameter (bool) as the previous value (true), when I would expect it to send null. It seems as if the value is being persisted somehow.
Any Ideas on how to resolve this issue? Much appreciated.
Controller code:
[HttpGet]
public ActionResult DischargeHuman(bool? HumanDischarged = null)
{
DischargeHumanViewModel dischargeHumanVM = new DischargeHumanViewModel();
dischargeHumanVM.HumanDischarged = HumanDischarged;
return View(dischargeHumanVM);
}
[HttpPost]
public ActionResult DischargeHuman(DischargeHumanViewModel dischargeHumanVM)
{
string username = HttpContext.User.Identity.Name.Substring(HttpContext.User.Identity.Name.LastIndexOf(#"\")).Trim('\\');
dischargeHumanVM.UserName = username;
if (ModelState.IsValid)
{
dischargeHumanVM.HumanDischarged = _adminTaskLogic.DischargeHuman(dischargeHumanVM.ClientID.Value, dischargeHumanVM.HumanID, dischargeHumanVM.UserName, dischargeHumanVM.DateOfDischarge.Value);
}
if (dischargeHumanVM.HumanDischarged.Value)
{
return RedirectToAction("DischargeHuman", new { dischargeHumanVM.HumanDischarged });
}
else
{
return View(dischargeHumanVM);
}
}
.cshtml code:
#using (Html.BeginForm())
{
#Html.ValidationSummary();
if (Model.HumanDischarged.HasValue)
{
if (Model.HumanDischarged.Value)
{
<span style="color:blue" id="msgSpan">Human successfully discharged.</span>
}
else
{
<span style="color:red" id="msgSpan">An error occurred.</span>
}
Model.PatientDischarged = null;
}
...
view model:
public class DischargePatientViewModel
{
public string UserName { get; set; }
[Required]
[Display(Name = "Client: ")]
public int? ClientID { get; set; }
[Required]
[Display(Name = "Patient ID: ")]
public string PatientID { get; set; }
[Required]
[Display(Name = "Date Of Discharge: ")]
public DateTime? DateOfDischarge { get; set; }
public bool? PatientDischarged { get; set; }
public IEnumerable<SelectListItem> SelectClientList
{
get { return new SelectList(new ClientLogic().GetClients(null, false, true), "ClientID", "ClientDisplayText"); }
}
}

pass a model from partial view to controller by ajax in mvc

My controller is
public ActionResult AddCustomer(Customer SM)
{
DataAccessLayer.ConClass obj = new DataAccessLayer.ConClass();
obj.SaveCustumerDetails(SM);
ModelState.Clear();
return PartialView();
}
my model is
public class Customer
{
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string Customer_id { get; set; }
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string Customer_Contact_Person { get; set; }
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string Customer_Contact_Person_Designation { get; set; }
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string Customer_name { get; set; }
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string Customer_Address1 { get; set; }
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string Customer_Address2 { get; set; }
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string Customer_City { get; set; }
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string Customer_State { get; set; }
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string Customer_Country { get; set; }
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string Customer_PIN { get; set; }
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string Customer_Phone1 { get; set; }
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string Customer_Phone2 { get; set; }
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string Customer_Email1 { get; set; }
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string Customer_Email2 { get; set; }
}
Savecutomer is the name of the button .My partaial view code is
<script>
$('#SaveCustomer').click(
function () {
$.ajax({
type: "POST",
url: '#Url.Action("AddCustomer", "Customer")',
data: ' $("myform").serialize() ,
contentType: 'application/json; charset=utf-8',
dataType: 'json',
complete: function (data) {
},
});
});
</script>
My need is to save customer details when i click on savecustomer button I don't want to see the details on url. In this way url holds data. I need to avoid it.
The method you have shown is a GET but its parameter is Customer SM which means that the DefaultModelBinder will generate a query string for each property in your model. I'm guessing that (because this method returns a partial view) your calling it in the main view using #Html.Action() or ajax to load a form into the view.
Firstly you need to methods, one GET and one POST
public ActionResult AddCustomer()
{
// Initialize a new instance of your model and pass it to the view
Customer model = new Customer();
return PartialView(model);
}
[HttpPost]
public JsonResult AddCustomer(Customer SM)
{
DataAccessLayer.ConClass obj = new DataAccessLayer.ConClass();
obj.SaveCustumerDetails(SM);
return Json(true); // see notes below
}
Note if you have included #Html.AntiForgeryToken in the partial, then your will also need to add [ValidateAntiForgeryToken]
Next, delete the script from your partial view and add it to the main view (scripts should never be in partials). Then change the script to
$('#SaveCustomer').click(function() {
$.ajax({
type: "POST",
url: '#Url.Action("AddCustomer", "Customer")',
data: $('#myform').serialize(), // change this to include the #
dataType: 'json',
success: function (data) {
// do something?
},
});
});
Note this assumes your form has id="myform". Note also contentType has been removed (its not required unless you stringify the data). It can also be simplified to
$.post('#Url.Action("AddCustomer", "Customer")', $('#myform').serialize(), function(data) {
// do something
});
Side notes: Its not clear what you want to do in the success callback. I would suggest that in the POST method you use return Json(true); if the save was successful, otherwise return a HTTP error code. Then in the success call back you might do something like
if (data) {
// the save was successful so reset existing form controls
$('#myform').get(0).reset();
// maybe display a message indicating success
}
and similarly you could handle an error by displaying a message indicating the the customer could not be saved.
When i changed to
$('#SaveCustomer').click(
function () {
$.ajax({
type: "POST",
url: '#Url.Action("AddCustomer", "Customer")',
data: "{'Customer_Name' : '" + $('#Customer_Name').val() + "' ," +
" 'Customer_Adress1' : '" + $('#Customer_Address1').val() + "'}" ,
contentType: 'application/json; charset=utf-8',
dataType: 'json'
});
})
and change controller to
public ActionResult AddCustomer(string Customer_Name, string Customer_Address1)
{
DataAccessLayer.ConClass obj = new DataAccessLayer.ConClass();
obj.SaveCustomerDetails( Customer_Name, Customer_Address1);
ModelState.Clear();
return PartialView();
}
it worksss

How to post a json object from to an mvc action

I have a mvc action
[HttpPost]
public ActionResult EditUser(ApplicationUser model)
ApplicationUser class is:
public class ApplicationUser
{
public int UserId { get; set; }
[Required]
public string UserName { get; set; }
public byte[] HashedPassword { get; set; }
public bool IsActive { get; set; }
public bool IsVerified { get; set; }
}
In jquery side I am doing:
$.ajax({
method: 'POST',
url: '#Url.Content("~/UserAdmin/EditUser")',
dataType: "json",
data: ....How do I post the object...???
});
My question is how do I post the Json object to the method as I hit the break point but the object is null.
Use JSON.stringify to reliably convert your JS object to JSON data for sending across the wire
var user = {
UserId: '31750',
UserName: 'chugh97',
HashedPassword: '...',
IsActive: true,
IsVerified: true
};
...
dataType: 'json',
data: JSON.stringify(user),
...
Note - I would recommend making your HashedPassword a string type instead of a byte[], it would be easier to deal with that client-side.

fill model's fields before post

i pass a model to my view . and it's fields are hiddenfor.
and my tds are here(in this view)
how can i say when i click on button(submit-btn2) , first my java script codes execute . and then my filled model will be post ?
my Partialview :
#Html.HiddenFor(m => m.username)
#Html.HiddenFor(m => m.Tell)
#Html.HiddenFor(m => m.Name)
#Html.HiddenFor(m => m.Mobil)
#Html.HiddenFor(m => m.Lname)
<button class="btn btn-medium btn-general input-block-level" id="submit-btn2" type="submit">save</button>
//all tds are here in this page(this view)
// $(document).ready(function () {
//$('#submit-btn2').click(function () {
//$("#username").val($(".tdBuyername").val());
//$("#Tell ").val($(".tdPhone").val());
//$("#Name ").val($(".tdRecievername").val());
//$("#Mobil ").val($(".tdMobile").val());
//$("#Lname ").val($(".tdLname").val());
//});
// });
<script type="text/javascript">
$("#submit-btn2").click(function () { saveMyModel();});
function SaveMyModel()
{
var e = document.getElementById("id_purchase");
var str = e.options[e.selectedIndex].value;
var e2 = document.getElementById("id_spend");
var str2 = e.options[e.selectedIndex].value;
$.ajax({
url: '#Url.Action("Save", "Home")',
type: 'POST',
contentType: 'application/json',
data: JSON.stringify({
jsonMyModel: {
username: $(".tdBuyername").val(),
Tell: $(".tdPhone").val(),
Name: $(".tdRecievername").val(),
Mobil: $(".tdMobile").val(),
Lname: $(".tdLname").val(),
id_purchase: $("# id_purchase ").val(str),
id_spend: $("# id_spend ").val(str2),
}
})
});
}
Mycontroller:
[HttpGet]
public ActionResult Customer()
{
var obj = new Project.Models.ModelClasses.ViewModelX();
return PartialView(obj);
}
[HttpPost]
public JsonResult Save(ViewModelX jsonMyModel)
{
var result = true;
if (ModelState.IsValid)
{
result= MyClass.Insert (jsonMyModel.Address, jsonMyModel.Cod,
jsonMyModel.idpurchase,
jsonMyModel.idspend, jsonMyModel.Lname,
jsonMyModel.Name, jsonMyModel.Tell, jsonMyModel.username);
}
else
{
}
return Json(result, JsonRequestBehavior.AllowGet);
}
MyClass:
public class ViewModelX
{
public Nullable< long > idpurchase { get; set; }
public Nullable<long> idspend { get; set; }
public string username { get; set; }
public string Name { get; set; }
public string Lname { get; set; }
public string Tell { get; set; }
public string Address { get; set; }
public string CodPosti { get; set; }
}
Just add the following to the end of your click handler:
$('#myForm').submit();
Where myForm is the id attribute of your form.
Assuming your controller action accepts a parameter matching the class that your view is typed to, the model binder should take care of it as usual.
Are you using a strongly typed model?
What you have described can be done in two ways.
Using AJAX to post your data without page reload.
Using normal form post to post data.
Using AJAX
Having assumed that your controller method is like:
[HttpPost]
public JsonResult Save(MyModel jsonMyModel)
{
//do saving stuff
}
where , your model MyModel looks like
public class MyModel()
{
public string Username { get; set;}
public string Tell { get; set;}
public string Name { get; set;}
public string Mobile { get; set;}
public string LastName { get; set;}
}
You can create the model that your controller method accepts using normal jquery or javascript and post it using AJAX as below:
$("#submit-btn2").click(function () { saveMyModel();});
function SaveMyModel()
{
$.ajax({
url: '#Url.Action("Method", "SomeController")',
type: 'POST',
contentType: 'application/json',
data: JSON.stringify({
jsonMyModel: {
Username: $("#username").val(),
Tell: $("#Tell ").val(),
Name: $('#listviewlabel').val(),
Mobile: $("#Name ").val(),
LastName:$("#Lname ").val()
})
});
}
Using normal form post
You can directly google out this thing. You can even find this in your account controller.

MVC3 (Razor) Json Stringified data returns null (ArgumentNullException)

I have:
VIEW
<script type="text/javascript">
function postData() {
var urlact = '#Url.Action("createDoc")';
var model = '#Html.Raw(Json.Encode(Model))';
alert(model);
$.ajax({
data: stringify(model),
type: "POST",
url: urlact,
datatype: "json",
contentType: "application/json; charset=utf-8",
success: function (result) {
window.location.href = '#Url.Action("CreateWordprocessingDocument","Movies")'
}
});
}
</script>
Controller
[HttpPost]
public void createDoc(string mov)
{
var movies = new JavaScriptSerializer().Deserialize<IEnumerable<Movie>>(mov);
//using movies...
}
Model
//[Serializable]
public class Movie
{
//Added Data Annotations for Title & Genre
public int ID { get; set; }
[Required(ErrorMessage = "Insert name")]
public string Title { get; set; }
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
[Required(ErrorMessage = "Inserist genre")]
public string Genre { get; set; }
[DataType(DataType.Currency)]
public decimal Price { get; set; }
}
Why when I post the stringified data from View (through the Ajax post function) to Controller (createDoc) it stops throwing a ArgumentNullException (seems the Model passed is empty)?
Any workaround/solution?
Note: without stringifying the model it all works, but I'm trying to stringify it cause the other way I've got some issues with the DateTime format.
Note/2: I've also tried replacing the string mov in the input parameters of the Controller action with IEnumerable movies, but it didn't work either.
You'r model is already JSON encoded hence you do not need to Stringify it. This is probably causing Invalid Json data hence why it is not decoded.
if your DateTime format is the issue then explain that issue so we can help solve it.
Adding to the comment #Jaimal's answer about JSON.NET configuration. I use the following:
public class JsonNetResult : JsonResult
{
public JsonNetResult()
{
Formatting = Formatting.None;
}
public Encoding ContentEncoding { get; set; }
public string ContentType { get; set; }
public object Data { get; set; }
public JsonSerializerSettings SerializerSettings { get; set; }
public Formatting Formatting { get; set; }
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
throw new ArgumentNullException("context");
var response = context.HttpContext.Response;
response.ContentType = !string.IsNullOrEmpty(ContentType) ? ContentType : "application/json";
if (ContentEncoding != null)
response.ContentEncoding = ContentEncoding;
if (Data == null)
return;
// If you need special handling, you can call another form of SerializeObject below
var serializedObject = JsonConvert.SerializeObject(Data, Formatting, new JavaScriptDateTimeConverter());
response.Write(serializedObject);
}
}
with
public abstract class BaseController : Controller
{
/// <summary>
/// Use JSON.NET
/// </summary>
protected override JsonResult Json(object data, string contentType, Encoding contentEncoding)
{
var result = new JsonNetResult
{
Data = data,
ContentType = contentType,
ContentEncoding = contentEncoding,
Formatting = Formatting.Indented
};
return result;
}
}
and
public JsonResult Get()
{
return Json(myModel, null, null);
}
You may use different Converters.

Resources