ASP.NET MVC Razor post form containing partial view - asp.net

I have a ASP.NET view containing a partial view. I reuse the partial view in several other views with different models. The important part of the view looks like this:
#Html.EditorFor(model => model.Title)
//TextArea inserted by partial view
#Html.TextArea("content", new { id = "mycontent" })
//Submit button here
The corresponding model:
public class Entry {
public int ID { get; set; }
public string Title { get; set; }
public string Content { get; set; }
}
And controller method:
public ActionResult Create([Bind(Include = "ID,Title,Content")] Entry entry) {
if (ModelState.IsValid) {
db.Entries.Add(entry);
db.SaveChanges();
...
}
}
How can I submit this form posting the content of the TextArea to the "Content" of the model without using code like #Html.TextArea(model => model.Content)? Do I have to use AJAX?

In your partial view instead of using
#Html.TextArea("content", new { id = "mycontent" })
use this :
#Html.TextArea("Content", new { id = "mycontent" })
and without using #Html.TextAreaFor() data will be bind to model property Content and you can get its value in Controller.

Related

dropdownlist in mvc _layout file in asp.net mvc

In my application i have a form with dropdownlist in _layout file.
After submitting form in View (I have many Views with same _Layout file) goto some Other controller view.
But i am getting always a error
Object reference not set to an instance of an object at dropdownlist.
My _HomeLayout.cshtml
#using (Ajax.BeginForm("Allpost", "User", new AjaxOptions() { HttpMethod = "GET", UpdateTargetId = "frmEmp" }))
{
#Html.Partial("_AllCategories", Model)
}
Partial View
#model Models.HomePageSearchVM
#Html.DropDownListFor(m => m.catlist, Model.CategoriesList, "Select Categorie")
HomeController
public ActionResult _AllCategories()
{
HomePageSearchVM pasvm = new HomePageSearchVM();
pasvm.CategoriesList = new MultiSelectList(db.CategoriesList, "CatId", "CategorieName");
return PartialView("_AllCategories", pasvm);
}
HomePageSearchVM.cs
namespace Entities
{
public partial class HomePageSearchVM
{
public virtual IEnumerable<SelectListItem> CategoriesList { get; set; }
[NotMapped]
public string[] catlist { get; set; }
public string search { get; set; }
}
}
View Home
#model Models.PostallVM
#{
Layout = "~/Views/Shared/_HomeLayout.cshtml";
}
----- some code ----
Error
Object reference not set to an instance of an object.
How use Form in _Layout file with some text and dropdown fields and call a model in Layout. I am using the same layout file for many Views with different Models.
I hope you understand my problem.

DropdownList value doesnt add to database

I can display the values from my database both in a dropdownlist and where the value is needed.
But I can't get the value from the dropdownlist to my database while creating something. it's getting null.
I've tried some solutions from s.o.f but they didnt't work.
Models 1:
public class Kategori
{
[Key]
public int KategoriID { get; set; }
public string Namn { get; set; }
}
Models 2:
public class Inlägg
{
[Key]
public int InläggsID { get; set; }
public Kategori Kategori { get; set; }
}
Controller:
// POST: Inlägg/Create
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Titel,Text,Kategori.Namn")] Inlägg inlägg)
//The Kategori is getting null
{
if (ModelState.IsValid)
{
inlägg.Datum = DateTime.Now;
_context.Add(inlägg);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(inlägg);
}
View:
#Html.DropDownList("Kategori", null, htmlAttributes: new { #class = "form-control" })
I've tried using SelectItemList, select with options values, having a SelectItem inside Models class also a "public Kategori List" inside Inlägg.
Don't really know how to solve this. I've just tried 8 hours today, and 2 hours yesterday.
How can I get the value that the user choosen in the dropdownlist instead of getting null? Tell me if I need to send more codes :-)
You should change it;
#Html.DropDownList("Kategori", null, htmlAttributes: new { #class = "form-control" })
to
#Html.DropDownList("SelectedCategory", ViewData["Kategori"] as SelectList, htmlAttributes: new { #class = "form-control" })
The selected dropdown element is passed to serverside as SelectedCategory.
Also, I strongly suggest you to use Model classes instead of ViewData to carry data between controller and view.
You need to add another property for the foreign key value. Since your other related entity class name is Kategori, you may name this new property KategoriId so that it matches the convention for the foreign key property names.
public class Inlagg
{
[Key]
public int InläggsID { get; set; }
public string Titel { get; set; }
public string Text { get; set; }
public DateTime Datum { get; set; }
public virtual Kategori Kategori { get; set; }
public int? KategoriId { set;get;} // This is the new property
}
Now in your form inside your view, make sure the select element rendered by the DropDownList helper has the same name attribute value as the new property name (check the view source of the page)
#Html.DropDownList("KategoriId", ViewData["Kategori"] as SelectList)
Now finally, make sure you include this new input name/property name inside the Bind attributes Include list so that the model binder will bind that.
public async Task<IActionResult> Create([Bind(Include="Titel,Text,KategoriId")]
Inlagg inlagg)
{
// to do : your code for saving and returning something
}
Another option is to use a view model with only needed properties, instead of using the Bind attribute with your entity class

get IEnumerable<T> in mvc post method argument

I have one model called ProductSupplier
I am passing #model IEnumerable to my View
and showing it from view
Now when i submit the form i m not getting list of IEnumerable in my http post method. I want to know the selected supplier from user.
Below is my model
public sealed class ProductSupplier
{
public int CountryId { get; set; }
public int UserId { get; set; }
public bool IsProductSupplier { get; set; }
public string CountryName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
}
This is my HttpGet method
public ActionResult ManageSupplier(int id)
{
var supplier = App.UsersRepo.GetSupplierForProduct(id);
return View(supplier);
}
And I am binding it via following way (U can suggest me best way I am new bee to MVC)
#model IEnumerable<ProductSupplier>
#using (Html.BeginForm("ManageSupplier", "Products", FormMethod.Post, new { role = "form") })
{ #Html.AntiForgeryToken()
foreach (var item in Model)
{
<div class="checkbox">
<label>
#Html.CheckBoxFor(x => item.IsProductSupplier, new { id = item.Email }) #item.FirstName #item.LastName (#item.Email)
</label>
</div>
}
}
And finally my HttpPost method
[HttpPost]
public ActionResult ManageSupplier(IEnumerable<ProductSupplier> obj)
{ // I m getting obj null in my argument
//I want to Get selected id from obj and want to pass in selectedSupplier
var returnVal = App.ProductRepo.AssigneSupplierForProduct(productId, selectedSupplier);
return Json(new { success = true }, JsonRequestBehavior.DenyGet);
}
can anyone suggest me where i m making mistake.
I am new to MVC any kind of suggestion highly appreciated.
Thank you in advance.
Firstable u cant do it like this.One way to do that is something like this.Here is the basic step how u do that.
1-assign for all checkbox ,checkbox change event with the unique id.
(take a look at here)
2-Cretae a jquery object and store the data when ever the checkbox clicked ,via versa
var ListProductSuppliers ={ {ProductSupplier_info_here },{ProductSupplier_info_here } };
3-later via ajax request,serilize this object(ListProductSuppliers ) and send to your method
4-on server side deserilize this to the IEnumerable<ProductSupplier>
5 later do it whatever u want with those selected suppliars

Transferring data entities from a DataService class to a view in MVC

I'm trying to learn MVC. I'm having some trouble understanding how to return data from my DataService class to my view. Here's the structure of my solution so far:
The solution contains two projects and a database. The first project is my DataService project that contains my Entity Model and my service class called AppDataService.
The second project is the website itself. It contains my HomeController, an Index view, and my inventory model which contains two models: An Item and the DB Context for Items called Catalog.
The goal of the application is to create a simple application that displays the inventory of a stock room and displays the information for a user. It's not for a homework assignment so there are no predefined objectives. I'm just trying to learn the MVC convention on my own. I realize that this is a pretty basic question, but I'm kind of at a dead end.
Here's my code:
AppDataServices:
public class AppDataService:IAppDataService
{
public Inventory GetItem(string srch)
{
Inventory item = null;
using (var data = new WCSDatabaseEntities())
{
item = data.Inventories.FirstOrDefault(x => x.Name == srch);
}
return item;
}
public List<Inventory> GetCatalog()
{
List<Inventory> catalog = null;
using (var data = new WCSDatabaseEntities())
{
catalog = data.Inventories.ToList();
}
return catalog;
}
public void Dispose()
{
}
}
My application's models:
public class Item
{
public int MediaId { get; set; }
public string Name { get; set; }
public int InStock { get; set; }
public decimal Price { get; set; }
public string Manufacturer { get; set; }
}
public class InventoryDbContext : DbContext
{
public DbSet<Item> Catalog { get; set; }
}
Currently, nothing I have tried has worked so my home controller's index action just returns the view, and the view currently doesn't accept a model. Can anyone help to explain how I take the returned entities and attach them to a model to send to the view? Thanks in advance! I realize this is a really basic question.
Edit: Here is the Home Controller.
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
}
At your most basic level you want something like:
public class HomeController : Controller
{
public ActionResult Index()
{
// Assuming you're not using an IoC container.
AppDataService appDataService = new AppDataService();
Inventory item = appDataService.GetItem("Albatross");
IndexViewModel model =
new IndexViewModel()
{
Name = item.Name
};
return View(model);
}
}
Create yourself a folder called /ViewModels/Home in the root of your MVC project and add a class called IndexViewModel:
public class IndexViewModel
{
public string Name { get; set; }
}
Then in your view (Index.cshtml):
#model MyNamespaceChangeMe.ViewModels.Home.IndexViewModel
<p>Here's your #Model.Name from the stock room.</p>

MVC Model State Validation fails on Listbox

I have a simple model which uses a multi select listbox for a many-many EF relationship.
On my Create action, I'm getting the error
The parameter conversion from type 'System.String' to type 'MyProject.Models.Location' failed because no type converter can convert between these types.
I have 2 models, an Article and a Location:
Article.cs
namespace MyProject.Models
{
public class Article
{
public Article()
{
Locations = new List<Location>();
}
[Key]
public int ArticleID { get; set; }
[Required(ErrorMessage = "Article Title is required.")]
[MaxLength(200, ErrorMessage = "Article Title cannot be longer than 200 characters.")]
public string Title { get; set; }
public virtual ICollection<Location> Locations { get; set; }
}
Location.cs:
namespace MyProject.Models
{
public class Location
{
[Key]
public int LocationID { get; set; }
[Required(ErrorMessage = "Location Name is required.")]
[MaxLength(100, ErrorMessage = "Location Name cannot be longer than 100 characters.")]
public string Name { get; set; }
public virtual ICollection<Article> Articles { get; set; }
}
}
I have a ViewModel:
namespace MyProject.ViewModels
{
public class ArticleFormViewModel
{
public Article article { get; set; }
public virtual List<Location> Locations { get; set; }
public ArticleFormViewModel(Article _article, List<Location> _locations)
{
article = _article;
Locations = _locations;
}
}
}
create.cshtml:
#model MyProject.ViewModels.ArticleFormViewModel
<h2>Create</h2>
#using (Html.BeginForm()) {
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>Article</legend>
<div class="editor-label">
#Html.LabelFor(model => model.article.Title)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.article.Title)
#Html.ValidationMessageFor(model => model.article.Title)
</div>
<h3>Locations</h3>
#Html.ListBoxFor(m=>m.article.Locations,new MultiSelectList(Model.Locations,"LocationID","Name"))
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
Finally my controller actions:
// GET: /Article/Create
public ActionResult Create()
{
var article = new Article();
var AllLocations = from l in db.Locations
select l;
ArticleFormViewModel viewModel = new ArticleFormViewModel(article, AllLocations.ToList());
return View(viewModel);
}
//
// POST: /Article/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Article article)
{
var errors = ModelState.Values.SelectMany(v => v.Errors);
if (ModelState.IsValid)
{
var locations = Request.Form["article.Locations"];
if (locations != null)
{
var locationIDs = locations.Split(',');
foreach (var locationID in locationIDs)
{
int id = int.Parse(locationID);
Location location = db.Locations.Where(l => l.LocationID == id).First();
article.Locations.Add(location);
}
}
db.Articles.Add(article);
db.SaveChanges();
return RedirectToAction("Index");
}
var AllLocations = from l in db.Locations
select l;
ArticleFormViewModel viewModel = new ArticleFormViewModel(article, AllLocations.ToList());
return View(viewModel);
}
This all works relatively well, my Locations listbox is populated properly:
If I do not select a Location then my model is saved properly. If I select one or more locations then my Model.IsValid check fails with the exception
The parameter conversion from type 'System.String' to type 'MyProject.Models.Location' failed because no type converter can convert between these types.
However if I remove the ModelState.IsValid check then despite the error my values are all correctly saved into the database - just that I lose validation for things such as the model title.
Hope someone can help!
Unless you create a type converter, you cannot directly bind the results of your list box directly to a complex object like that. The reason lies in the fact that MVC can only deal with posted HTTP values, which in this case are an array of strings that contain the selected ID's. Those strings do not directly map to your Locations object (ie the number 1 cannot be directly converted to a Locations object with an ID of 1).
Your best bet is to have a list of location ID's in your View Model of type string or int to accept the posted values, then in your post method create the Location objects and fill them with the correct ID's.
FYI, the reason your code works is because you are bypassing the model binding and going directly to the Request.Form collection. You will notice that the bound Article object will not have any Location objects.
EDIT:
I don't even see how your code would work even without this problem. Your ArticleFormViewModel does not have a parameterless constructor, so that will fail in model binding (unless you have a custom model binder).
In any event, what you want to do is this (note, you will have to populate SelectedLocationIDs if you want them to be selected when the view is rendered):
public class ArticleFormViewModel
{
...
List<int> SelectedLocationIDs { get; set; }
...
}
Then, in your view you have:
#Html.ListBoxFor(m=>m.SelectedLocationIDs,
new MultiSelectList(Model.Locations,"LocationID","Name"))
In your Post method, instead of the code that calls Request.Form, you have something like this:
foreach(var locationID in article.SelectedLocationIDs) {
... // look up your locations and add them to the model
}

Resources