I'm working on an application that uses a View Model to pass data to a view, however when I attempt to save changes the user makes to the data and post it back to the controller for processing and storing in a database, I'm getting null values for everything in my view model. I've tried various other questions on here and none of the answers I've found have been able to solve this issue. I think it has something to do with the my use of a ListBox to display some of the data, but I'm fairly new to ASP.net MVC 5 and am not quite sure what I need to be doing here.
Below is the code for my view model, the relevant sections from the controller, and the view.
View Model
public class OrganizationViewModel
{
public Organization Organization { get; set; }
public IEnumerable<SelectListItem> RelatedContacts { get; set; }
}
Sending Data from Controller to View
[HttpGet]
public ActionResult Edit(Organization organization)
{
IEnumerable<SelectListItem> contactsList = GetContacts(organization);
var viewModel = new OrganizationViewModel()
{
Organization = organization,
RelatedContacts = contactsList
};
return View("Edit", viewModel);
}
Receiving Data from View
[HttpPost]
public ActionResult SaveOrganization(OrganizationViewModel organizationViewModel)
{
organizationViewModel.Organization.Id = (int)TempData["Id"];
organizationViewModel.Organization.LastEdited = DateTime.Today;
organizationViewModel.Organization.DateAdded = (DateTime)TempData["DateAdded"];
TempData.Clear();
if (ModelState.IsValid)
{
organizationRepository.SaveOrganization(organizationViewModel.Organization);
return RedirectToAction("Index", "Organization");
}
IEnumerable<SelectListItem> contactsList = GetContacts(organizationViewModel.Organization);
var viewModel = new OrganizationViewModel()
{
Organization = organizationViewModel.Organization,
RelatedContacts = contactsList
};
return View("Edit", viewModel);
}
The Edit View
<div class="panel">
<div class="panel-heading">
<h3>Editing #(Model.Organization.Name)</h3>
</div>
#using (Html.BeginForm("SaveOrganization", "Organization", FormMethod.Post))
{
<div class="panel-body">
#Html.HiddenFor(m => Model.Organization.Name)
<div class="row">
<div class="col-md-3 form-group">
<label>Organization Name</label>
#Html.TextBox("Name", null, new { #class = "form-control" })
</div>
<div class="col-md-3 form-group">
<label>Address</label>
#Html.TextArea("Address", null, new { #class = "form-control" })
</div>
</div>
<div class="row">
<div class="col-md-3 form-group">
<label>Related Contacts</label>
#Html.ListBox("RelatedContacts", Model.RelatedContacts, new { #class = "form-control", size = 10 })
</div>
<div class="col-md-3 form-group">
<label>Custom Fields</label>
<br />
<input type="button" value="Add New Field" class="btn btn-default" />
</div>
</div>
<div class="row">
<div class="col-md-12 form-group">
<label>Notes</label>
#Html.TextArea("Notes", null, 10, 500, new { #class = "form-control", #style = "width: 100%; max-width: 100%;" })
</div>
</div>
</div>
<div class="panel-footer">
<input type="submit" value="Save" class="btn btn-primary" />
#Html.ActionLink("Cancel and return to List", "CancelEditOrAdd", null, new { #class = "btn btn-default" })
</div>
}
Answering my own question for anyone who stumbles across this and wants to see the exact changes I made based on #Stephen Muecke's comments.
Changed all the #html.something()s into #html.somethingfor()s for fixed the issue with not receiving postback data for the Organization in the View Model, and then I created a new property in the view model to correspond with the selected index in the ListBox, which now reads #Html.ListBoxFor(m => m.SelectedIndexes, Model.RelatedContacts, ...). I'm now getting all the proper postback data and can relate the selected index to the Organization's related contacts.
Edit: Also changed my View Model to contain the properties of my Organization class and not an actual Organization object itself as a property.
Related
I'm having some trouble with data being sent through my controller, here's a simplified example:
public ActionResult EditNote(NotesModel model)
{
model.Author = Session["UserName"].ToString();
model.Note = null;
model.Title = null;
return View(model);
}
On my views page the data shown from the model is the exact same as how it was received by the method and all changes are ignored, why?
Bigger picture:
I'm trying to have a user edit an existing note in the database, if they're the one who made it of course. based on whether or not they're the author they will either edit the existing note or create a new note, this is where the problem lies. The controller is supposed to set all the values of the model to null so that on the views page they will be empty.
Editing an existing note is no problem however emptying the model so the editing page is blank does not work.
EDIT
This is my view page:
#model WebsiteProject.Models.NotesModel
#{
ViewBag.Title = "";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#section Sidebar
{
<div id="sidebarheadericon" style="background-image: url('../Content/icons/apps.png')"></div>
<div id="headertext"><h1>Welcome</h1></div>
<hr id="seperator" />
<p class="psidebar">test</p>
<p>
#Html.ActionLink("Create New", "EditNote")
</p>
}
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h1>NotesModel</h1>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<p class="control-label">Note by #Session["UserName"].ToString()</p>
<div class="form-group">
#Html.LabelFor(model => model.Title, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Title, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Title, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Note, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Note, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Note, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="largebtn" />
</div>
</div>
<p class="text-danger">#ViewBag.NoteViewError</p>
</div>
}
<div>
#Html.ActionLink("Back to List", "NoteApp")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Here you can see the data that is received (dummy data)
Now here you'll see that the data of the model is changed
Yet on the website it is not changed
The biggest problem isn't the Note and Title not being changed because the user can do that, but the Id and Author, which the user cannot, and should not be able to change.
This is related to the fact that you are using EditorFor:
#Html.EditorFor(model => model.Note, new { htmlAttributes = ... })
It so happens that EditorFor not only uses the Model object, it also uses ModelState which keeps a copy of all values for all Model items that were received, parsed and validated, along with any validation errors that this may have produced.
As long as ModelState has a value for that model item, it will be shown by EditorFor. The reason is that user input may be invalid, like entering 12X for an int Model property. EditorFor will show 12X if the form is re-rendered, which is coming from ModelState, and which could never come from Model.
Unwanted values can be removed by calling Remove, like this:
ModelState.Remove("Note");
On a different note, the ViewModel class that you are using here is not suited to the needs of this action method. It may be better to create a dedicated ViewModel class for it, with fewer properties, which you can then convert to the ViewModel type that the View needs.
I think you want to tell the incoming notes model is a new one or an existing one, here is some code to try,
public ActionResult EditNote(NotesModel model)
{
if(model.Id > 0) //assuming existing notes has id or any other ways you want to check
{
//save data
return View(model);
}
else //if Id has a value <= 0, return a new model with only Author set, maybe the Id (depending on how you want to generate the Id)
{
var model = new NotesModel();
model.Author = Session["UserName"].ToString();
return Viwe(model);
}
}
I have a shared partial view which consist of a form. This partial view is shared between two different controller. Let's call them Controller1 and Controller2. The problem is, whether I am using the Controller1's Insert view or Controller2's Insert view, the action method Insert of Controller1 is always being called.
Let's say I am filling the form at the localhost:58888/Controller2/Insert and then push the submit button, in this situation the Insert action of Controller1 is operated and debugger never reached to Controller2's Insert method. After a summary of my problem, I would like to share with you some of my code.
Here is the shared partial view;
#model TabNetMVC.Models.EOrder.Product
<div class="panel panel-default">
<div class="panel-body">
<div class="form-horizontal">
<div class="form-group" lang="tr">
#Html.Label("Ürün Adı", new { #class = "control-label col-md-2 text-left" })
<div class="col-md-4">
#Html.DropDownListFor(model => model.Name,
new List<SelectListItem> {
new SelectListItem {
Text="Test-1",
Value="1",
},
new SelectListItem {
Text="Test-2",
Value="2",
},
}, "Kategori Seçiniz", new { #class = "form-control", id = "itemDropDown" })
<p style="display: none; color: red;" id="dropdownValidation">Lütfen Ürün Seçiniz!</p>
</div>
</div>
<div class="form-group" lang="tr">
#Html.Label("Miktar", new { #class = "control-label col-md-2 text-left" })
<div class="col-md-4">
#Html.TextBoxFor(model => model.Quantity, new { #class = "form-control", id = "itemQuantity" })
#Html.ValidationMessage("Quantity", "", new { #class = "text-danger" })
<p style="display: none; color: red;" id="quantityValidation">Lütfen Miktar Seçiniz!</p>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-4">
<button class="btn btn-success col-lg-4" type="submit" id="btnAdd" onclick="return Validation(#((int)Enums.MissingItem.Add))"><i class="fa fa-plus" aria-hidden="true"></i> Add</button>
</div>
</div>
</div>
</div>
</div>
Here, Product model which is used at this shared view is a base class of both of other two models which is being used by Controller1 and Controller2. I tried to make us of polymorphism to make this shared view as generic as possible.
Lastly, I am sharing two different action method of each Controller.
Controller1's Insert method;
[HttpPost]
public ActionResult Insert(MissingProduct product)
{
if (SessionHelper.Products == null)
{
SessionHelper.Products = new List<Product>();
}
if(product.Statu == (int)Enums.MissingItem.SendConfirm)
{
//Operations for inserting into database placed here...
SessionHelper.Products = new List<Product>();
}
else if (product.Statu == (int)Enums.MissingItem.Add && ModelState.IsValid)
{
SessionHelper.Products.Add(product);
}
return PartialView("~/Views/EOrder/ItemListControl.cshtml");
}
Controller 2's Insert method;
[HttpPost]
public ActionResult Insert(SupplementaryProduct product)
{
if (SessionHelper.Products == null)
{
SessionHelper.Products = new List<Product>();
}
if (product.Statu == (int)Enums.MissingItem.SendConfirm)
{
//Operations for inserting into database placed here...
SessionHelper.Products = new List<Product>();
}
else if (product.Statu == (int)Enums.MissingItem.Add && ModelState.IsValid)
{
SessionHelper.Products.Add(product);
}
return PartialView("~/Views/EOrder/ItemListControl.cshtml");
}
As you see, both of action methods are almost identical except the data type is MissingProduct at Controller1's Insert method and SupplementaryProduct at the Controller2's Insert method. Lastly note that, both of the Insert action has its own view which renders this shared partial view into itself.
What can be causing this? Thanks in advance...
This looks like an issue with the form definition. When you define a form, you tell it which URL to submit itself to. And I suspect this is where the problem is, it is somehow declared to always submit to Controller1.
So in your shared view check the declaration of the form, either with <form> or with Html.BeginForm or with Ajax.BeginForm.
Ozan. can you expose and checks the action attribute value of the form in the shared partial view?
...<form ... action='/Controller1/Insert' ...>
In many cases this causes the extrange behavior.
Please checks any html helper that renders your form code ...
Thanks
I spent some time on this problem. I'm passing a ViewModel back from my View to the Controller via a form HttpPost. However, only SelectedItemId has value. Users and Rights are null.
View model UserRightViewModel
public class UserRightViewModel
{
public string SelectedItemId { get; set; }
public SelectList Users;
public List<RightViewModel> Rights { get; set; }
}
View model RightsViewModel
public class RightsViewModel
{
public int ID { get; set; }
public string Name{ get; set; }
public bool isSelected { get; set; }
}
Controller Post
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index(UserRightsViewModel _viewModel)
{
UserRightsViewModel viewModel = _viewModel;
/*value _viewModel = null for Users and Rights
/* code stuff */
return View(viewModel);
}
View
#model Web.ViewModels.UserRightsViewModel
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="content-wrapper">
<!-- Content Header (Page header) -->
<section class="content-header">
<h1>
#ViewBag.Title
</h1>
#*<ol class="breadcrumb">
<li><i class="fa fa-dashboard"></i> Home</li>
<li>Examples</li>
<li class="active">Blank page</li>
</ol>*#
</section>
<!-- Main content -->
<section class="content">
<!-- Default box -->
<div class="box">
<div class="box-header with-border">
<div class="box-tools pull-right">
<button type="button" class="btn btn-box-tool" data-widget="collapse" data-toggle="tooltip" title="Collapse">
<i class="fa fa-minus"></i>
</button>
<button type="button" class="btn btn-box-tool" data-widget="remove" data-toggle="tooltip" title="Remove">
<i class="fa fa-times"></i>
</button>
</div>
</div>
<br />
<div class="form-group">
#Html.LabelFor(model => model.SelectedItemId, "User", new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(m => m.SelectedItemId, Model.Users, new { onchange = "redirect(this.value)", #class = "form-control" })
#Html.ValidationMessageFor(model => model.SelectedItemId)
</div>
</div>
<br />
<div class="box-body">
#for (int i = 0; i < Model.Rights.Count(); i += 2)
{
<div class="row form-group">
<div class="col-md-6">
<div class="row">
<div class="col-md-4">
<div class="col-md-6">
</div>
<div class="col-md-6">
#Html.CheckBoxFor(model => model.Rights.ElementAt(i).isSelected, new { #class = "checkbox checkbox-center" })
#Html.ValidationMessageFor(model => model.Rights.ElementAt(i).isSelected, "", new { #class = "text-danger" })
</div>
</div>
<div class="col-md-8">
#Model.Rights.ElementAt(i).Denumire
</div>
</div>
</div>
<div class="col-md-6">
<div class="row">
<div class="col-md-4">
<div class="col-md-6">
</div>
<div class="col-md-6">
#Html.CheckBoxFor(model => model.Rights.ElementAt(i + 1).isSelected, new { #class = "checkbox checkbox-center" })
#Html.ValidationMessageFor(model => model.Rights.ElementAt(i + 1).isSelected, "", new { #class = "text-danger" })
</div>
</div>
<div class="col-md-8">
#Model.Rights.ElementAt(i + 1).Name
</div>
</div>
</div>
</div>
}
<br />
<br />
<div class="form-group">
<div class="row">
<div class="col-md-6">
<div class="col-md-9">
</div>
<div class="col-md-3">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</div>
<div class="col-md-6">
#Html.ActionLink("Cancel", "Index", null, new { #class = "btn btn-danger" })
</div>
</div>
</div>
</div>
</div>
</section>
</div>
}
I have no idea why some values are null. Why some of values are sent and some not?
Users is null because your not (and nor should you) creating and input for each property of each SelectListItem in the SelectList (if you need to return the view you re-populate the value in the POST method). And in any case, its a field, not a property (has no { get; set; }) so the DefaultModelBinder cannot set it).
Rights is null because you cannot use .ElementAt() to generate form controls for a collection (inspect the html your generating and you will see that the name attributes have no relationship to your model). The name attributes need to be
<input name="Rights[0].ID" ... />
<input name="Rights[0].Name" ... />
<input name="Rights[0].isSelected" ... />
<input name="Rights[1].ID" ... />
<input name="Rights[1].Name" ... />
<input name="Rights[1].isSelected" ... />
....
Note that your only generating a for control for the isSelected property which on its own would be meaningless in the POST method and you will an least want to include a hidden input for the ID property.
It appears from your code that you want to generate a 2 column layout, in which case your code should be (simplified)
<div class="row form-group">
#for(int i = 0; i < Model.Rights.Count; i++)
{
<div class="col-md-6">
#Html.HiddenFor(m => m.Rights[0].ID)
#Html.CheckBoxFor(m => m.Rights[0].isSelected)
</div>
// End current 'row' and start a new one every 2nd item
if ((i + 1) % 2 == 0)
{
#:</div><div class="row form-group">
}
}
</div>
Hi here is answer for your doubt, some values are posting and some values are not.
Actually you are getting the correct result and everything works perfectly
I said this because, if you bind selectedid and selectlistitem to the dropdownlistfor helper, then you will get only selectedid which was assigned as a name for the dropdownlist control. so when post, browser has sent name value pair.
This is same reason for checkbox also , which property has binded to the name that only you will get it in the post.
Hope above information was helpful
Thanks
Karthik
I can see you put submit button outside form. so form not submitting property.
I want to retrieve data from a view, it should work like this:
User fill a form available on the webpage
User clicks SEARCH button
Some function(s) collect the data and display them in another view
I tried all the basic tutorials and tips on others stackoverflow question but it still doesn't work. I don't know what I'm doing wrong...
Here's my code from the view:
section id="roomSearch">
<div class="banner">
<div class="banner-info">
<div class="container">
<div class="details-1">
#using (Html.BeginForm("UploadRoomSearchData", "HomeController", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div class="col-md-10 dropdown-buttons">
<div class="col-md-3 dropdown-button">
#Html.AntiForgeryToken()
<div class="input-group">
#Html.TextBoxFor(m => m.YourName, new { #class = "form-control has-dark-background", #placeholder = "Imię" })
#Html.ValidationMessageFor(m => m.YourName, "", new { #class = "text-danger" })
<!--<input class="form-control has-dark-background"
name="slider-name" id="slider-name" placeholder="Imię" type="text" required="">-->
</div>
</div>
<!---strat-date-piker---->
<link rel="stylesheet" href="~/Content/jquery-ui.css" />
<script src="~/Scripts/jquery-ui.js"></script>
<script>
$(function () {
$("#datepicker,#datepicker1").datepicker();
});
</script>
<!---/End-date-piker---->
<div class="col-md-3 dropdown-button">
<div class="book_date">
<form>
<input class="date" id="datepicker" type="text" value="Przyjazd" onfocus="this.value = '';" onblur="if (this.value == '') {this.value = 'Przyjazd';}">
<!-- #Html.TextBoxFor(m => m.CheckIn, new { #class = "date" })
#Html.ValidationMessageFor(m => m.CheckIn, "", new { #class = "datefield" })-->
</form>
</div>
</div>
<div class="col-md-3 dropdown-button">
<div class="book_date">
<form>
<input class="date1" id="datepicker1" type="text" value="Wyjazd" onfocus="this.value = '';" onblur="if (this.value == '') {this.value = 'Wyjazd';}">
<!--#Html.TextBoxFor(m => m.CheckOut, new { #class = "date1" })
#Html.ValidationMessageFor(m => m.CheckOut, "", new { #class = "datefield" })-->
</form>
</div>
</div>
<div class="col-md-3 dropdown-button">
<div class="section_1">
<select id="country" onchange="change_country(this.value)" class="frm-field required">
<option value="null">Dwuosobowy</option>
<option value="null">Jednoosobowy</option>
<option value="AX">Apartament</option>
<option value="AX">Gościnny</option>
</select>
</div>
</div>
<div class="clearfix"> </div>
</div>
<div class="col-md-2 submit_button">
<form >
<input type="submit" value="SZUKAJ">
<!-- <p> #Html.ActionLink("SZUKAJ", "Book1", "Home")</p>-->
</form>
</div>}
And here's my code in the controller. For now I try to retrieve only a name, to see if it's working.
[HttpPost]
public ActionResult UploadRoomSearchData(FormCollection form)
{
string name = Request["YourName"].ToString();
StringBuilder sbRoom = new StringBuilder();
sbRoom.Append("<b>Amount :</b> " + name + "<br/>");
//return RedirectToAction("Book1");
return Content(sbRoom.ToString());
}
I also tried something like this:
foreach(var v in form)
{
Write.Response("name:" + v);
}
I tried your code and it seems to work.
First I have the controller method to display the form
public ActionResult CreatePerson()
{
Person model = new Person();
return View(model);
}
Then the form:
#model RetrieveDataFromaView.Models.Person
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Person</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.YourName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.YourName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.YourName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="submit" class="btn btn-default" />
</div>
</div>
</div>
}
Which does a post to the controller method
[HttpPost]
public ActionResult CreatePerson(FormCollection formCollection)
{
string name = Request["YourName"].ToString();
StringBuilder sbRoom = new StringBuilder();
sbRoom.Append("<b>Amount :</b> " + name + "<br/>");
return Content(sbRoom.ToString());
}
This returns a view with only the content of the StringBuilder.
Maybe you are looking for RedirectToAction?
Hello you have this line inside the form:
#Html.AntiForgeryToken()
You can remove it or add the corresponding attribute to use it:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult CreatePerson(FormCollection formCollection)
{
///Your code here
}
Basically this is a token generated for the server to avoid requests from forms not generated by the server.
You have many ways of retrieving data from a form Post in ASP.NET MVC.
Using a Model
Usually, forms are created by specifying a Model type in the Razor view. You can use that type to retrieve the data. ASP.NET MVC will parse the body and populate the object in parameter for you.
Ex:
Controller:
public class HomeController: Controller
{
[HttpGet]
public ActionResult Index()
{
return View(new Person());
}
[HttpPost]
public ActionResult Index(Person p)
{
//Just for the sake of this example.
return Json(p);
}
}
Razor view
#model WebApplication2.Models.Person
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<title>title</title>
</head>
<body>
<div>
#using (Html.BeginForm("Index", "Home", FormMethod.Post))
{
#Html.AntiForgeryToken()
<div>
#Html.LabelFor(m => m.FirstName): <br/>
#Html.TextBoxFor(m => m.FirstName)
</div>
<div>
#Html.LabelFor(m => m.LastName): <br/>
#Html.TextBoxFor(m => m.LastName)
</div>
<input type="submit" value="Submit" />
}
</div>
</body>
</html>
Using a FormsCollection
The FormsCollection object allows you to access the raw values of a form. It acts as a Dictionary for the Forms value. This is useful, especially when you have a dynamic model to parse, or if you just plain don't know about the Model type.
It's also pretty straightforward to use.
[HttpPost]
public ActionResult Index(FormCollection form)
{
var dict = form.AllKeys.ToDictionary(key => key, key => form[key]);
return Json(dict);
}
PS: I saw you are using Request[key]. It may just be me, but this call just looks like Dark magic, where you get data from who knows where (it uses the Query String, the cookies, the Request body, etc. It seems like it could be really problematic in some cases in the future. I much prefer knowing exactly where the data comes from. But that may just be me.
Conclusion
In conclusion, use the Model approach if you know exactly what should be in the Form. Use the FormCollection approach if you really need to. That's pretty much it.
Good luck.
I am looking for a way to validate two fields on ASP View page. I am aware that usual way of validating form fields is to have some #model ViewModel object included on a page, where the properties of this model object would be annotated with proper annotations needed for validation. For example, annotations can be like this:
[Required(ErrorMessage = "Please add the message")]
[Display(Name = "Message")]
But, in my case, there is no model included on a page, and controller action that is being called from the form receives plane strings as method arguments.
This is form code:
#using (Html.BeginForm("InsertRssFeed", "Rss", FormMethod.Post, new { #id = "insertForm", #name = "insertForm" }))
{
<!-- inside this div goes entire form for adding rssFeed, or for editing it -->
...
<div class="form-group">
<label class="col-sm-2 control-label"> Name:</label>
<div class="col-sm-10">
<div class="controls">
#Html.Editor("Name", new { htmlAttributes = new { #class = "form-control", #id = "add_rssFeed_name" } })
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label"> URL:</label>
<div class="col-sm-10">
<div class="controls">
#Html.Editor("Url", new { htmlAttributes = new { #class = "form-control", #id = "add_rssFeed_Url" } })
</div>
</div>
</div>
</div>
</div>
<!-- ok and cancel buttons. they use two css classes. button-styleCancel is grey button and button-styleOK is normal orange button -->
<div class="modal-footer">
<button type="button" class="button-styleCancel" data-dismiss="modal">Close</button>
<button type="submit" class="button-styleOK" id="submitRssFeed">Save RSS Feed</button>
</div>
}
You can see that form is sending two text fields (Name and Url) to the RssController action method, that accepts these two string parameters:
[HttpPost]
public ActionResult InsertRssFeed(string Name, string Url)
{
if (!String.IsNullOrEmpty(Name.Trim()) & !String.IsNullOrEmpty(Url.Trim()))
{
var rssFeed = new RssFeed();
rssFeed.Name = Name;
rssFeed.Url = Url;
using (AuthenticationManager authenticationManager = new AuthenticationManager(User))
{
string userSid = authenticationManager.GetUserClaim(SystemClaims.ClaimTypes.PrimarySid);
string userUPN = authenticationManager.GetUserClaim(SystemClaims.ClaimTypes.Upn);
rssFeedService.CreateRssFeed(rssFeed);
}
}
return RedirectToAction("ReadAllRssFeeds", "Rss");
}
If the page would have model, validation would be done with #Html.ValidationSummary method, but as I said I am not using modelview object on a page.
Is there a way to achieve this kind of validation without using ModelView object, and how to do that? Thanks.
If you are looking for server side validation you can use something like below using
ModelState.AddModelError("", "Name and Url are required fields.");
but you need to add
#Html.ValidationSummary(false)
to your razor view inside the Html.BeginForm section, then code will looks like below.
[HttpPost]
public ActionResult InsertRssFeed(string Name, string Url)
{
if (String.IsNullOrEmpty(Name.Trim()) || String.IsNullOrEmpty(Url.Trim()))
{
ModelState.AddModelError("", "Name and URL are required fields.");
return View();
}
var rssFeed = new RssFeed();
rssFeed.Name = Name;
rssFeed.Url = Url;
using (AuthenticationManager authenticationManager = new AuthenticationManager(User))
{
string userSid = authenticationManager.GetUserClaim(SystemClaims.ClaimTypes.PrimarySid);
string userUPN = authenticationManager.GetUserClaim(SystemClaims.ClaimTypes.Upn);
rssFeedService.CreateRssFeed(rssFeed);
}
return RedirectToAction("ReadAllRssFeeds", "Rss");
}
If you are looking for only client side validation, then you have to use client side validation library like Jquery.
http://runnable.com/UZJ24Io3XEw2AABU/how-to-validate-forms-in-jquery-for-validation
Edited section for comment
your razor should be like this.
#using (Html.BeginForm("InsertRssFeed", "Rss", FormMethod.Post, new { #id = "insertForm", #name = "insertForm" }))
{
#Html.ValidationSummary(false)
<div class="form-group">
<label class="col-sm-2 control-label"> Name:</label>
<div class="col-sm-10">
<div class="controls">
#Html.Editor("Name", new { htmlAttributes = new { #class = "form-control", #id = "add_rssFeed_name" } })
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label"> URL:</label>
<div class="col-sm-10">
<div class="controls">
#Html.Editor("Url", new { htmlAttributes = new { #class = "form-control", #id = "add_rssFeed_Url" } })
</div>
</div>
</div>
</div>
</div>
<!-- ok and cancel buttons. they use two css classes. button-styleCancel is grey button and button-styleOK is normal orange button -->
<div class="modal-footer">
<button type="button" class="button-styleCancel" data-dismiss="modal">Close</button>
<button type="submit" class="button-styleOK" id="submitRssFeed">Save RSS Feed</button>
</div>
}
Hope this helps.