Get model from partial view to controller - asp.net-mvc

Is it possible to pass model to controller with #Html.Partial?
Using plain <td> in view return list of rows, while this exact same <td> wrapped in partial returns null on form submit
#using ( Html.BeginForm() )
{
<table>
<tr>
<th></th>
</tr>
<tr>
#for ( int i = 0; i < Model.Rows.Count; i++ )
{
#*<td class="row">Book #Html.DisplayFor(x => Model.Rows[i].RowNum) #Html.DropDownListFor(x => Model.Rows[i].Selected, Model.Rows[i].Data) </td>*#
#Html.Partial("Row", Model.Rows[i])
}
</tr>
</table>
<input type="submit" value="Submit" />
}

Html.Partial renders a partial view.
If your view is already expecting a model of that type, you can pass it along.
#Html.Partial("ViewName", Model)
To send values to an action of a controller, you can try using Html.Action
#Html.Action("actionName","ControllerName", new {RowNum = Model.Row[i].RowNum})
You can pass values using the anonymous object

You probably want to use the RenderPartial Extension, it should give you what you need.

Related

How can I call a controller method in a view using ASP.NET CORE

I have a controller with a method that returns a value:
public float GetShoppingCartTotal()
{
string user = User.Identity.Name;
var total = _context.ShutterOrders.Where(c => c.User == user).Select(c => c.Price * c.Amount).Sum();
return total;
}
How can I call this method from a view so I can show its value, here is my view (P.S. I took out some code of the view since I think it really is unnecessary for the purpose of this question. I have marked the part where I would like to call my controller function):
#model IEnumerable<ShuttersInc.Areas.Identity.Data.ShutterOrders>
<tfoot>
<tr>
<td colspan="3" class="text-right">Total:</td>
<td class="text-right">
**I'd like to place it here**
</td>
</tr>
</tfoot>
P.P.S - I have an IEnumerable model since I list items from a list. I think this is one of the main problems why I can't call the method from the controller, although I might be mistaken.
Your wrong solution must first in controller in action return view with modle:
public IActionResult GetShoppingCartTotal()
{
string user = User.Identity.Name;
var total = _context.ShutterOrders.Where(c => c.User == user).Select(c
=> c.Price * c.Amount).Sum();
return View("viewName",total );
}
then in view :
#model string
<tfoot>
<tr>
<td colspan="3" class="text-right">#Model</td>
<td class="text-right">
**I'd like to place it here**
</td>
</tr>
</tfoot>

Model retains it's value after Submit to server

I'm facing this weird problem ,unable to make sense of it,I have a form which accepts Person Id and then reads the data from an API and fills the UI for person Edit purposes.
Here is the markup of this form,I'm guessing its has something to do with Model binding as I have two Form tag and both having the same Model Id.
#using (Html.BeginForm("UpdatePerson", "Person", FormMethod.Get))
{
<table>
<tr>
<td colspan="2">
<h3>Read Person for Edit</h3>
</td>
</tr>
<tr>
<td>
<label>#Html.LabelFor(m => m.Id)</label>
</td>
<td>
#Html.TextBoxFor(m => m.Id)
</td>
</tr>
<tr>
<td colspan="2">
<input type="submit" name="btnReadPerson" value="Read Person" />
</td>
</tr>
</table>
}
#using (Html.BeginForm("UpdatePerson", "Person", FormMethod.Post))
{
<table>
<tr>
<td>
<label>#Html.LabelFor(m => m.Id)</label>
</td>
<td>
#Html.TextBoxFor(m => m.Id, new { #readonly = "readonly" })
</td>
</tr>
<tr>
<td>
<label>#Html.LabelFor(m => m.Type)</label>
</td>
<td>
#Html.TextBoxFor(m => m.Type)
</td>
</tr>
I have stripped the view,I tried to kept it brief.
Below is the Action which handles the Get
[HttpGet]
[ActionName("UpdatePerson")]
public ActionResult UpdatePersonRead(PersonEditModel model)
{
if (model.Id.HasValue)
{
var apiClient = new ApiClient (ApiVersions.v1);
var segmentReplaceList = new Dictionary<string, string> { { "{id}", model.Id.Value.ToString() } };
bool ApiHitStatus = false;
var result = apiClient.MakeAPIRequest(out ApiHitStatus, ResourceUriKey.Person, segmentReplaceList, HttpVerbs.Get, string.Empty);
model = new PersonEditModel();
if (ApiHitStatus)
{
var personToBeUpdated = JsonConvert.DeserializeObject<RootChildPerson>(result);
if (personToBeUpdated != null)//Assigning json obj to model
{
model.NameFirst = personToBeUpdated.name_first;
model.NameLast = personToBeUpdated.name_last;
model.NameMiddle = personToBeUpdated.name_middle;
model.SocialSecurityNumber = personToBeUpdated.social_security_number;
model.SubType = PersonHelper.SubTypeValue(personToBeUpdated.sub_type);
model.Type = "person";
model.DateOfBirth = personToBeUpdated.date_of_birth;
model.Id = personToBeUpdated.id;
}
}
}
return View(model);
}
Now since the Person Id 4 does not corresponds to any person ,so I receive Null json object which upon conversion to C# class results in an empty (not null because it has every property set to null or empty) personToBeUpdated object which is then assigned to the model,I have checked model.Id becomes null in the Controller and even in the View ,but somehow it assigns input value that is 4 (it was null) to both Person Id textboxes.
Kindly let me know whats happening here.
Well as commented by #StephenMuecke ,So I cleared model before updating it.
model = new PersonEditModel();
ModelState.Clear();
Its also interesting to note that view takes data from ModelState instead of current specified model,
HtmlHelpers controls (like .TextBoxFor() etc.) don't bind to model values on Postback, but rather get their value directly out of the POST buffer from ModelState.
Taken from ASP.NET MVC Postbacks and HtmlHelper Controls ignoring Model Changes

Unable to pass the same object with different result to partial view on the Home/Index controller in mvc 3

public ActionResult Index()
{
List<pInfo> pobj = new List<pInfo>();
pobj = (from pid in db.pInfoes
orderby pid.pId descending
select pid).ToList();
return View(pobj);
}
public ActionResult toprank() ///partial view
{
List<pInfo> pobj = new List<pInfo>();
pobj = (from pid in db.pInfoes.Where(c => c.DateCreated < DateTime.Now)
orderby pid.Score descending
select pid).Take(3).ToList();
return PartialView("toprank", pobj);
}
\\\ Index.csHtml
#model IEnumerable<TestProj.pInfo>
<table>
<tr>
<td>
#foreach (var item in Model)
{
<table>
<tr>
<td>
<iframe width="560"
height="300"
src="#item.pUrl"
frameborder="0"></iframe>
</td>
</tr>
</table>
}
</td>
<td>
#{Html.RenderPartial("toprank", model);}
</td>
</tr>
</table>
I am passing different result set for same Model i.e pInfo. on partial view and Index actionresult on the Home Controller. When I am trying to render the partial view on the Index view page I am getting the same result-set from the Index action result two times one in the table and another in the #{Html.RenderPartial("toprank", model);} ... I am sure I am missing some basic understanding of how the partial view works but unable to figure it out for last 3 hrs. If I change the url to partial view i.e (home/toprank ) then I get the resultset I want but its not coming on the Home/Index page
Please let me know if my design concept is wrong.. I am starting to feel that this is probably the wrong approach to get this working..
if you want to see the toprank() called you need to use Html.Action not partial, change the view to this :
<td>
#Html.Action("toprank")
</td>

Passing value from EditorFor to controller

This is my view where education is the list in the model.
#using chpayroll.Models.CustInformations
#model CustInfoExtract
#Html.HiddenFor(x => x.flag, new { #id = "flag" })
#Html.HiddenFor(x => x.StaffId)
<table style=" width:730px">
<tr>
<th>Country</th>
<th>Board</th>
<th>Level</th>
<th>PassedYear</th>
<th>Division</th>
</tr>
<tr>
#Html.EditorFor(x => x.education)
</tr>
<tr>
<td><input type="submit" value="Add Another" id="addedu"/> </td>
</tr>
</table>
I have editor template as below
#using staffInfoDetails.Models
#model staffInfo.education
#Html.HiddenFor(x=>x.staffId)
<tr>
<td >#Html.DropDownListFor(x => x.country, Model.countryList, "--select--", new { #id="country"})</td>
<td>#Html.TextBoxFor(x => x.board, new { #id="board"})</td>
<td>#Html.TextBoxFor(x => x.level, new { #id="level"})</td>
<td>#Html.TextBoxFor(x => x.passedYr, new { #id="passedYr"})</td>
<td>#Html.DropDownListFor(x => x.passedDiv, Model.passedDivList, "--select--", new { #id="division"})</td>
</tr>
I am trying to pass model from controller to view and back from view to controller. While I was passing model to view, the education list passed, but, when i tried to pass model from view to controller, everything else passed except for the education list. How can I solve this problem ?
Only the selected value from the drop down list will be posted back so you'll need to re-populate your drop down list if validation fails (ie. if the View has to be re-displayed).
Your POST action might look something along the lines of the following:
[HttpPost]
public ActionResult Home(CustInformations viewModel)
{
if (!ModelState.IsValid)
{
// Re-populate drop-down list and redisplay form
viewModel.DropdownListOptions = _repository.getEductionList();
return View(viewModel);
}
// Validation passed
// Save, update, etc and redirect to new page
}

How do I return List or Collection to Controller from View in MVC 3?

Someone please help me return this list properly from my view. I don't see why I'm returning null for my fieldModelList I try to pass to the controller...
Here is my view:
#model List<Regions.SOA.UI.CopyBookSchemaCreator.Models.FieldModel>
<script type="text/javascript" src="~/Scripts/jquery-ui-1.8.11.min.js"></script>
#using (Html.BeginForm("GetResponse", "TestMethods", FormMethod.Post))
{
<table id="tblMethods">
<tr>
<th>
Property Name
</th>
<th>
Request
</th>
</tr>
#foreach (FieldModel fieldModel in Model)
{
<tr>
<td>
#Html.DisplayFor(m => fieldModel.PropertyName)
</td>
<td>
#Html.TextBoxFor(m => fieldModel.PropertyValue)
</td>
</tr>
}
</table>
<div>
<input type="submit"/>
</div>
and here is my controller:
[HttpPost]
public ActionResult GetResponse(List<FieldModel> fieldModelList)
{
return GetResponse(fieldModelList);
}
I am hitting the HttpPost method but if I place a breakpoint just inside it, I am returning null for the fieldModelList right off the bat, which I was hoping would be a list of the values I entered into the texboxes on the view that is of model FieldModel...
I think something is wrong with my logic versus my syntax, or as maybe as well as my syntax, but basically what I want to do is return back a list of type FieldModel with each corresponding PropertyName and PropertyValue to the controller. I noticed I am not passing any kind of id parameter in my BeginForm statement in the view. Do I need one here?
Just in case, here is my model class for FieldModel:
namespace Regions.SOA.UI.CopyBookSchemaCreator.Models
{
public class FieldModel
{
[Display(Name = "Property")]
public string PropertyName { get; set; }
[Display(Name = "Value")]
public string PropertyValue { get; set; }
}
}
Phil Haack wrote an article some time ago explaining how to bind collections (ICollection) to view models. It goes into additional detail about creating an editor template, which you could certainly do as well.
Basically, you need to prefix the HTML elements' name attributes with an index.
<input type="text" name="[0].PropertyName" value="Curious George" />
<input type="text" name="[0].PropertyValue" value="H.A. Rey" />
<input type="text" name="[1].PropertyName" value="Ender's Game" />
<input type="text" name="[1].PropertyValue" value="Orson Scott Card" />
Then, your controller could bind the collection of FieldModel
[HttpPost]
public ActionResult GetResponse(List<FieldModel> fieldModelList)
{
return GetResponse(fieldModelList);
}
I'm not 100% sure the following would name the attributes correctly (I'd recommend using the editor template) but you could easily use the htmlAttributes argument and give it a name using the index.
#for(int i = 0;i < Model.Count;i++)
{
<tr>
<td>
#Html.DisplayFor(m => m[i].PropertyName)
</td>
<td>
#Html.TextBoxFor(m => m[i].PropertyValue)
</td>
</tr>
}
Editor Template
If you wanted to go as far as adding an editor template, add a partial view named FieldModel.ascx to /Views/Shared that is strongly typed to a FieldModel
#model Regions.SOA.UI.CopyBookSchemaCreator.Models.FieldModel
#Html.TextBoxFor(m => m.PropertyName) #* This might be a label? *#
#Html.TextBoxFor(m => m.PropertyValue)
And, then the part of your view responsible for rendering the collection would look like:
#for (int i = 0; i < Model.Count; i++) {
#Html.EditorFor(m => m[i]);
}

Resources