Alright I've been with this issue for 2 days. For simplicity I'll write code as less as possible.
I'm using the same controller both for viewing and saving data. My domain class, view, controller are as follows (I'm having issue with the last prop public DateTime CreatedOn, the whole problem is explained at the end so you can skip to it first):
Domain Class:
public partial class Admin_TestCategory
{
[Key]
[Column(Order = 0)]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public short TestCategoryId { get; set; }
[StringLength(100)]
[Column(Order = 1)]
[Required]
public string TestCategoryName { get; set; }
[Column(Order = 2)]
public int? CreatedBy { get; set; }
[Column(Order = 3)]
public DateTime CreatedOn { get; set; }
}
View:
#model BOL.Entities.Admin.Admin_TestCategory
#{
ViewBag.Title = "Edit Category";
Layout = "~/Views/Admin/_Admin.cshtml";
}
#using (Html.BeginForm("EditTestCategory", "Admin", FormMethod.Post))
{
<div class="row">
<div class="col-lg-12">
<fieldset>
<legend>Edit Category</legend>
<div class="form-group row">
#Html.HiddenFor(m => m.TestCategoryId)
#Html.LabelFor(m => m.TestCategoryName, "Category Name :", new {#class = "col-lg-2"})
#Html.TextBoxFor(m => m.TestCategoryName, new {#class = "col-lg-3 form-control"})
<div class="col-lg-1"></div>
#Html.LabelFor(m => m.CreatedBy, "Created By :", new {#class = "col-lg-2"})
#Html.TextBoxFor(m => m.CreatedBy, new {#class = "col-lg-3 form-control"})
</div>
<div class="form-group row">
<div class="col-lg-6">
<button type="submit" class="btn btn-primary form-group col-lg-2">Update</button>
</div>
<div class="col-lg-6">
<div class="row">
#Html.LabelFor(m => m.CreatedOn, "Created On :", new {#class = "col-lg-4"})
#Html.TextBoxFor(m => m.CreatedOn, "{0:dd-MM-yyyy}", new {Name = Html.NameFor(m => m.CreatedOn), #class = "col-lg-6 form-control datepicker" })
</div>
</div>
</div>
</fieldset>
</div>
</div>
}
and the Controller:
// GET /Admin/EditTestCategory
[HttpGet]
public ActionResult EditTestCategory(Admin_TestCategory newTestCategory)
{
var testCatService = new TestCategoryService();
var oldTestCategory = testCatService.GetById(newTestCategory.TestCategoryId);
//check if that category exists or not
//category does not exist
if (oldTestCategory == null)
return HttpNotFound("Can not find the ID of the given Test Category");
//category exists
return View(oldTestCategory);
}
// POST /Admin/UpdateTestCategory
[HttpPost]
public ActionResult UpdateTestCategory(Admin_TestCategory newTestCategory)
{
var testCatService = new TestCategoryService();
var oldTestCategory = testCatService.GetById(newTestCategory.TestCategoryId);
//check if that category exists or not
//category does not exist
if (oldTestCategory == null)
return HttpNotFound("Can not find the ID of the given Test Category");
//category exists
//check if the new data is changed or not
//data is not changed
var o = JsonConvert.SerializeObject(oldTestCategory);
var n = JsonConvert.SerializeObject(newTestCategory);
if (o == n)
return RedirectToAction("TestCategory", "Admin");
//data is changed
testCatService.UpdateTestCategory(newTestCategory);
return RedirectToAction("TestCategory", "Admin");
}
How the controller works is all written with comments. The way it works is, when this controller is hit for first time it will only have the id property then it will fetch other data using that property and fill the View. Then when I hit the button of my view this controller's parameter will have all the changed data and hence it will update database. The only problem is when the controller is hit for 2nd time, it gets all the other data through model binding but only the last one CreatedOn which is a DateTime. I provided Name attribute to make sure it binds the model but it doesn't, in the controller the date becomes reset, although in the browser I inspected it and yes it has the exact Name that it needs.
I tried to make this form POST, tried to add attribute [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd/MM/yyyy}")] in the DateTime prop in my domain class but it doesn't work because in view its a TextBoxFor and I need it that way for auto validation. So what else should I try?
UPDATE
I have split the controller in 2, one for showing all data using GET another for updating all data using POST. Still same problem.
Add Below code to your Post action it will helpful to findout which field is causing error.
I tried executing your code on my machine and it seems error with "Date" format. try using "{0:MM/dd/yyyy}"; format in your code it will resolve your error.
foreach (ModelState modelState in ViewData.ModelState.Values)
{
foreach (ModelError error in modelState.Errors)
{
var errorMsg = error.ErrorMessage;
}
}
Happy Coding :)
Updated: Add DisplayFormat attribute in ur model property as it is in ur view code
as per the comments, You need to have a separate GET and POST action. On the Get action you need to find the item you want to edit and return it as a View Model:
public ActionResult EditTestCategory(short id)
{
var testCatService = new TestCategoryService();
var categoryToEdit = testCatService.GetById(id);
//check if that category exists or not
//category does not exist
if (categoryToEdit == null)
return HttpNotFound("Can not find the ID of the given Test Category");
return View(categoryToEdit);
}
Then you need a POST action that accepts the edited model like so:
[HttpPost]
public ActionResult EditTestCategory(Admin_TestCategory viewModel)
{
var testCatService = new TestCategoryService();
Admin_TestCategory categoryToEdit = testCatService.GetById(viewModel.TestCategoryId);
if(ModelState.IsValid)
{
categoryToEdit.TestCategoryName = viewModel.TestCategoryName;
categoryToEdit.CreatedBy = viewModel.CreatedBy;
//etc
testCatService.UpdateTestCategory(categoryToEdit);
}
return RedirectToAction("TestCategory", "Admin");
}
The other issue you have is that CreatedBy is data type int? in Admin_TestCategory.cs
In your view you're using:
#Html.TextBoxFor(m => m.CreatedBy, new { #class = "col-lg-3 form-control" })
If you change to:
#Html.EditorFor(m => m.CreatedBy, new { #class = "col-lg-3 form-control" })
Model Binds Fine
Related
I'm fairly new to ASP.Net MVC so forgive me for anything that should just be obvious.
I have an object that contains a property that is a list. I only don't know how I should implement this in the create.
this is the object:
public class TeamMember
{
public int TeamMemberId { get; set; }
public string FristName { get; set; }
public string LastName { get; set; }
public DateTime BirthDate { get; set; }
public string Biographie { get; set; }
public virtual Image Image { get; set; }
public virtual List<DanGrade> DanGrades { get; set; }
}
In the create view I want to be able to select multiple Dangrades.
I tried to modify an editor Template for it that looks like this:
#using BudoschoolTonNeuhaus.Models
#model BudoschoolTonNeuhaus.Models.TeamMember
#{
var db = new ApplicationDbContext();
var danGrades = db.DanGrades.ToList();
}
<select multiple name="#ViewData.TemplateInfo.HtmlFieldPrefix" class="dropdown">
#foreach (var dan in danGrades)
{
<option value="#">
#dan.DanGradeId: #dan.BudoSport, #dan.Grade
</option>
}
</select>
but this does not give the result that I thought it would, its just showing mutiple dangrade labels in the create view that you can see here:
#model BudoschoolTonNeuhaus.Models.TeamMember
#{
ViewBag.Title = "Create";
Layout = "~/Views/Shared/_Admin_Layout.cshtml";
}
<div class="wrapper">
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>TeamMember</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.FristName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.FristName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.FristName, "", new { #class = "text-danger" })
</div>
</div>
.... // controls for other properties of model
<div class="form-group">
#Html.LabelFor(model => model.DanGrades, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.DanGrades, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.DanGrades, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Image, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<input type="file" id="Image" name="Image" hidden />
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
</div>
current HTML output:
Thanks for you help in advance!
To create a <select multiple> you use the ListBoxFor() method in your view.
But your model needs two properties to generate a listbox, a IEnumerable<int> to bind the selected values to (assumes the ID proeprty of DanGrade is typeof int), and an IEnumerable<SelectListItem> to display the <option> elements.
You editing data, so always start with a view model
public class TeamMemberVM
{
public int? TeamMemberId { get; set; }
....
[Display(Name = "DanGrades")]
public IEnumerable<int> SelectedDanGrades { get; set; }
public IEnumerable<SelectListItem> DanGradesList { get; set; }
}
and your view will be
#model yourAssembly.TeamMemberVM
....
#Html.ListBoxFor(m => m.SelectedDanGrades, Model.DanGradesList, new { #class="dropdown" })
and your controller methods will be
public ActionResult Create()
{
TeamMemberVM model = new TeamMemberVM();
ConfigureViewModel(model);
// For an Edit method, your would set the existing selected items here
model.SelectedDanGrades = ...
return View(model);
}
public ActionResult Create(TeamMemberVM model)
{
if (!ModelState.IsValid)
{
ConfigureViewModel(model); // repopulate the SelectList
return View(model);
}
// model.SelectedDanGrades contains the ID's of the selected options
// Initialize an instance of your data model, set its properties based on the view model
// Save and redirect
}
private void ConfigureViewModel(TeamMemberVM model)
{
IEnumerable<DanGrade> danGrades = db.DanGrades();
model.DanGradesList = danGrades.Select(x => new SelectListItem
{
Value = x.DanGradeId.ToString(),
Text = x.??? // the name of the property you want to use for the display text
});
}
Note also that your view has a file input so your view model needs a HttpPostedFileBase property to bind the file to
public HttpPostedFileBase Image { get; set; }
and in the view
#Html.TextBoxFor(m => m.Image, { new type ="file" })
Shouldn't your model be like that ?
[UIHint("NameOfTheEditorTemplate")]
public virtual List<DanGrade> DanGrades { get; set; }
Be sure to put the EditorTemplate under one of these two paths
~/Views/Shared/EditorTemplates
~/Views/Controller_Name/EditorTemplates
As explained in this post
So you are trying to save a list of custom objects inside your object. First of all, know that if you try to save teammember to a database your list of objects will not save. I've experienced this same issue and its needs some special configuring to get just that to work.
Second you can't select custom objects from a < select >. Select returns string[] to your controller. So objects, no. You can't return complex items like that using select directly.
What you can do is return a string[] and use the individual strings (maybe it contains name, maybe it contains id?) and then use that array to pull each object to your teammember object in the controller from the dangrade db context (I'm assuming that is where they are stored).
So for example if you Go back to your controller and add (string[] dangrades) to your parameters. Your parameters now looks something like this (string[] dangrades, Bind[blahblah] ... teammember).
Now after referencing the other database you can do as follows
teammember.Dangrades = new list<Dangrade>();
foreach(string item in dangrades)
{
var dangradeselected = from x in db.dangrades where x.name = item select x;
var dangradefromlinq = dangradeselected.tolist();
teammember.Dangrades.Add(dangradefromlinq[0]);
}
If you had previously stored dangrades in some other format (ie not a database) then you will have to append your code, or ask specifically with that for a better answer.
Also don't forget to give your select and id= (lookup html attributes) so that the controller can recognize it.
You can probably make this (pseudo)code a little neater. Also don't forget about possible null values.
If you want to save a list of items for each teamember you can also look into having 2 databases. I'm not sure if this is recommended. But you can have one for teammembers, and one for dangrades. In the case of dangrades you would add an additional property called grouping id that would match the id of your teammember. So when you pull up your teammember you could also pull up all related dawngrades that match its database id.
That's everything I can think of. If you find a simpler solution by all means go with that.
I am a new to MVC and still learning! I am trying to create a very basic App in my web which allows users to convert money value according to their preference. I made the web APi and was successful to call the service to my forms. However, in my controller I managed to get the currencies (names) to the index view, but cannot post the form back once entering a value in the text box to generate the partial view! What am I doing wrong in my codes?!
Currency Controller
namespace MVC_ATM.Controllers
{
public class CurrencyController : Controller
{
[HttpGet]
// GET: Currency
public ActionResult Index()
{
CurrenciesClient Cur = new CurrenciesClient();
var listCurrency = Cur.findAll();
SelectList list = new SelectList(listCurrency,"Id", "CurrencyName");
ViewBag.listCurrencies = list;
return View();
}
[HttpPost]
public ActionResult Index(Currencies cur)
{
if (!ModelState.IsValid)
{
string errors = string.Join("<br />", ModelState.Values
.SelectMany(x => x.Errors)
.Select(x => x.ErrorMessage));
return new ContentResult { Content = errors };
var rate = Convert.ToDecimal(cur.ConversionRate);
if (cur.CurrencyName == cur.CurrencyName)
{
ModelState.AddModelError("CurrencyCountry", "Can't make the conversion for the same value");
}
else if (cur.CurrencyName != cur.CurrencyName)
{
foreach (var currency in cur.CurrencyName)
{
ViewBag.Theresult = rate * cur.Value;
}
return PartialView("_CurrencyValue");
}
}
return View();
}
}
}
Currencies Model
namespace Project.Model
{
public class Currencies
{
public int Id { get; set; }
public string CurrencyName { get; set; }
public string CurrencyCountry {get; set;}
public decimal Value { get; set; }
public string ConversionRate { get; set; }
}
}
Index View
#model Project.Model.Currencies
#{
ViewBag.Title = "Index";
}
<h2>Currency</h2>
<body>
<div class="converter">
Convert: #Html.TextBoxFor(m => m.ConversionRate, new { #size = "5" })
<div class="form-group">
#Html.Label("Convert from", new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.DropDownList("Currency List", ViewBag.listCurrencies as SelectList, "Please Select a currency")
</div>
</div>
<div class="form-group">
#Html.Label("Convert to", new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.DropDownList("Currency List", ViewBag.listCurrencies as SelectList, "Please Select a currency")
</div>
</div>
<div>
<button type="submit" class="btn btn-primary">Convert</button>
</div>
</div>
</body>
Couple of things to notice, is the POST action and missing form tag in the view . You created a POST action that accepts Currencies model but the form doesn't post that. Only ConversionRate will bind to the model. To get the "Currency From" and "Currency To" and the "Conversion Rate" you will require a different approach/small changes.
ConversionModel.cs a new Model for index page that will capture your required fields.
public class ConversionModel
{
[Required]//decimal would be better but up to you requirement
public decimal ConversionRate { get; set; }
[Required]
public int FromCurrencyId {get;set;}
public SelectList FromCurrencies {get;set;}
[Required]
public int ToCurrencyId {get;set;}
public SelectList ToCurrencies {get;set;}
}
Get: while there is nothing wrong with what you've done, lets use a model approach and tightly bind it.
public ActionResult Index()
{
CurrenciesClient Cur = new CurrenciesClient();
var listCurrency = Cur.findAll();
ConversionModel model = new ConversionModel();
model.FromCurrencies = new SelectList(listCurrency,"Id", "CurrencyName");
model.ToCurrencies = new SelectList(listCurrency,"Id", "CurrencyName");
return View(model);
}
Post: Important thing here to notice is the SelectList will not be posted back. Only the ConversionRate, FromCurrencyId and ToCurrencyId are sent back not the Lists. If error occurs you will need to rebuild the lists and send it back in the model.
[HttpPost]
public ActionResult Index(ConversionModel curModel)
{
if(ModelState.IsValid)
{
if(curModel.FromCurrencyId ==curModel.ToCurrencyId)
{
//do something if same currecnies and return.
}
else
{
//Get the currencyList with rates from db
//use currency ToCurrencyId and FromCurrencyId to fetch the 2 currencies
// perform conversion with curModel.ConversionRate with existing logic
}
}
//Don'f forget to rebuild the Select Lists...
return View(curModel);
}
View:
#model Project.Model.ConversionModel
#{
ViewBag.Title = "Index";
}
#using (Html.BeginForm("Index", "Currency", FormMethod.Post)
{
#Html.TextBoxFor(m => m.ConversionRate, new { #size = "5" })
#* Please check the syntax *#
#Html.DropDownListFor(m => m.FromCurrencyId , Model.FromCurrencies as SelectList)
#Html.DropDownListFor(m => m.ToCurrencyId , Model.ToCurrencies as SelectList)
<button type="submit" class="btn btn-primary">Convert</button>
}
Not a CUT_COPY_PASTE. please do check for errors if any. It is only an approach.
ajax POST probably the next thing to learn... Let us know.
You need to put your items inside a form like this:
#using (Html.BeginForm("Index", "Currency", FormMethod.Post)
{
// Your form items
}
Not sure what I'm doing wrong, but my dropdown doesn't want to select the value I want it to select. I have the following
Controller actions
// GET: /Contract/Create
public ActionResult Create()
{
var model = new ContractViewModel();
var authors = _authorService.GetAuthors();
var publishers = _publisherService.GetPublishers();
model.AuthorsList = new SelectList(authors, "AuthorID", "Name", authors.First());
model.PublishersList = new SelectList(publishers, "PublisherID", "Name", publishers.First());
return View(model);
}
// POST: /Contract/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(ContractViewModel contractViewModel)
{
if (ModelState.IsValid)
{
Contract contract = new Contract();
contract.CanUsePublisherPartners = contractViewModel.CanUsePublisherPartners;
contract.Author.AuthorID = Convert.ToInt32(contractViewModel.SelectedAuthorID);
contract.Publisher.PublisherID = Convert.ToInt32(contractViewModel.SelectedPublisherID);
var success = _contractService.AddContract(contract);
if (success)
{
return RedirectToAction("Index");
}
}
contractViewModel.AuthorsList = new SelectList(_authorService.GetAuthors(), "AuthorID", "Name");
contractViewModel.PublishersList = new SelectList(_publisherService.GetPublishers(), "PublisherID", "Name");
ViewBag.ErrorMessage = "An error occured when trying to add the Contract. A contract between this Author and Publisher may already exist! Please try again and if the problem persists, contact the Sys Admin.";
return View(contractViewModel);
}
ViewModel
public class ContractViewModel
{
[Display(Name = "Can the author distribute through the publisher's partners?")]
public bool CanUsePublisherPartners { get; set; }
[Display(Name="Author")]
public int? SelectedAuthorID { get; set; }
[Display(Name = "Publisher")]
public int? SelectedPublisherID { get; set; }
public SelectList AuthorsList { get; set; }
public SelectList PublishersList { get; set; }
}
View binding of drop down lists
<div class="form-group">
#Html.LabelFor(model => model.SelectedAuthorID, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.HiddenFor(m => m.SelectedAuthorID)
#Html.DropDownListFor(m => m.SelectedAuthorID, Model.AuthorsList)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.SelectedPublisherID, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.HiddenFor(m => m.SelectedPublisherID)
#Html.DropDownListFor(m => m.SelectedPublisherID, Model.PublishersList)
</div>
</div>
What's the problem?
When I submit my form, the values of SelectedAuthorID and SelectedPublisherID are the default of int - 0.
I am really at wits end here, I looked at some details trying to find out if they impact anything. E.g. some people had trouble when the Selected container property had the same name as the value property of the list items and so forth.
If anyone has any suggestions would be great to share them!
I believe the issue is that you have the SelectedPublisherID and SelectedAuthorID on the page twice.
The Html.HiddenFor(m => m.SelectedAuthorID) should not be necessary alongside the DropDownListFor.
A minor thing, general C# naming conventions use PascalCase, which means that the properties should be named SelectedAuthorId instead of ID.
This is my model:
[Display(Name = "Company")]
public int CompanyId { get; set; }
public SelectList Companies { get; set; }
Setting Data for view
[HttpGet]
[AllowAnonymous]
public ActionResult Index()
{
var model = new Ticket
{
Companies = new SelectList(new List<SelectListItem> { new SelectListItem { Text = "0", Value = "0" } }, "Value", "Text")
};
return View(model);
}
The View:
<div class="form-group">
#Html.LabelFor(m => m.CompanyId, new { #class = "col-md-6 col-md-pull-1 control-label" })
<div class="col-md-3 col-md-pull-1">
#Html.DropDownListFor(m => m.CompanyId, Model.Companies, new { #class = "selectpicker form-control" })
</div>
</div>
Results:
How can i get the SelectList to be posted back to the Controller so i dont have to keep populating it?
Model.Companies wont be binded because is not in the Form, the ModelBinder is looking for an input in the Form or a querystring value with the name of the property (in this case Companies) but you don´t have one in the view with that name, on the contrary, you have a field with the name CompanyId, that´s why the property CompanyId is binded.
A good way to save your Companies list and get it in the Post action is to use TempData, with TempData you can save an item in an action, and it´ll be available to the next action. Is like Session, but just for one Request.
I'm trying to create HttpPost method to create a new database entry. It should take 2 foreign IDs from different database tables and "name". Here's the model:
public class Domena
{
public int DomenaID { get; set; } // this domains ID
public int TLDID { get; set; } // foreign id
public int KlientID { get; set; } // foreign id
public string Nazwa { get; set; }
public virtual TLD TLD { get; set; }
public virtual Klient Klient { get; set; }
}
Right, so basically this is what I have now :
// GET: /Domena/Add_Domain
public ActionResult Add_Domain()
{
ViewBag.TLDID = new SelectList(db.TLDs, "TLDID", "Typ");
ViewBag.KlientID = new SelectList(db.Klienci, "KlientID", "KlientID");
return View();
}
//
// POST: /Domena/Add_Domain
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Add_Domain(Domena domena)
{
if (ModelState.IsValid)
{
db.Domeny.Add(domena);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.TLDID = new SelectList(db.TLDs, "TLDID", "Typ", domena.TLDID);
ViewBag.KlientID = new SelectList(db.Klienci, "KlientID", "KlientID", domena.KlientID);
return View(domena);
}
The way it works now is, it will display a drop-down list from which I can choose TLDID by "Typ" and KlientID by "KlientID" entry in the database. Also it ask for a "Nazwa", which is name that has to be written.
I want to remove the option to choose the KlientID from the dropdownlist and instead make HttpPost take the KlientID from the link. Example :
I go to client's details page : /Klient/Details/6
I click on Add_Domain link which takes currently viewed KlientID and takes me to: /Domena/Add_Domain/6
So, my question is, how can I modify both Get and Post methods in order to create a new "domena" entry in the database to the client's id which is in the link ?
Do I have to change anything in view as well ?
Here is my current Add_Domain view fieldset :
<fieldset>
<legend>Domena</legend>
<div class="editor-label">
#Html.LabelFor(model => model.TLDID)
</div>
<div class="editor-field">
#Html.DropDownList("TLDID", String.Empty)
#Html.ValidationMessageFor(model => model.TLDID)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.KlientID)
</div>
<div class="editor-field">
#Html.DropDownList("KlientID", String.Empty)
#Html.ValidationMessageFor(model => model.KlientID)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Nazwa)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Nazwa)
#Html.ValidationMessageFor(model => model.Nazwa)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
Thanks in advance!
If you use the default MVC routes {controller}/{action}/{id} you should able to leverage the id parameter. The Add_Domain link in your client page would set a route value:
#Html.ActionLink("Add a domain", "Add_Domain", "Domena",
new { id = Model.KlientID }, null)
You give the GET action a parameter and set this parameter on the model:
public ActionResult Add_Domain(int id)
{
ViewBag.TLDID = new SelectList(db.TLDs, "TLDID", "Typ");
var model = new Domena { KlientID = id };
return View(model);
}
And in your view you remove label and validation message for KlientID and replace the drop down list by a hidden input:
#Html.HiddenFor(model => model.KlientID)
In the POST action you only remove the ViewBag.KlientID = ... line. The rest can remain unchanged. The MVC model binder will bind the hidden field to the domena.KlientID property.
The id parameter is a bit misused here because this id usually is related to the model the Domena controller is dealing with, so usually a DomenaID and not a KlientID. But it should still work. I would consider to use a query parameter instead to make it clearer that the last parameter in the route is a KlientID:
The action link would be:
#Html.ActionLink("Add a domain", "Add_Domain", "Domena",
new { klientID = Model.KlientID }, null)
And the GET action is:
public ActionResult Add_Domain(int klientID)
{
ViewBag.TLDID = new SelectList(db.TLDs, "TLDID", "Typ");
var model = new Domena { KlientID = klientID };
return View(model);
}
POST action is the same. The created link is then /Domena/Add_Domain?klientID=6.