how to set dynamic controller name in the partial page - c#

I have a partial page it is using two View page different controller but there have same Edit Action method. i need to set controller name dynamically for particular page in the run time . how can i do it ?
My partial page _SearchProduct in the shared folder it is working only for WomanController action method Edit:
<div class="row">
<div class="col-md-6">
#using (Html.BeginForm("Edit", "Woman", FormMethod.Get))
{
<p>
Find by Product Id : #Html.TextBox("SearchString", ViewBag.CurrentFilter as string)
<input type="submit" value="Search" />
</p>
}
</div>
<div class="col-md-6">
<span style="color:green">#ViewBag.ProductName </span>
</div>
<span style="color:red"> #ViewBag.FindResult </span>
</div>
My WomanController EDIT page :
#model MKL.Models.WomanProduct
<hr />
#Html.Partial("~/Views/Shared/_SearchProduct.cshtml")
<hr />
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true)
#Html.HiddenFor(model => model.WomanProductId)
#if (ViewBag.ProductId != null)
{
#Html.Hidden("ProductId", (int)ViewBag.ProductId)
}
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
My ManController EDIT page :
#model MKL.Models.ManProduct
<hr />
#Html.Partial("~/Views/Shared/_SearchProduct.cshtml")
<hr />
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true)
#Html.HiddenFor(model => model.ManProductProductId)
#if (ViewBag.ProductId != null)
{
#Html.Hidden("ProductId", (int)ViewBag.ProductId)
}
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
SO need to dynamically set Partial view Controller name Man and Woman
#using (Html.BeginForm("Edit", "", FormMethod.Get)){}

You can pass a model to the partial controller:
#Html.Partial("~/Views/Shared/_SearchProduct.cshtml", Model)
In _SearchProduct.cshtml, Model will be of type WomanProduct or ManProduct, depending on the view that called Partial. Then, choose controller depending on the model type:
#{
var ctrl = Model is WomanProduct ? "Woman" : "Man";
}
#using (Html.BeginForm("Edit", ctrl, FormMethod.Get))

Well, I would suggest you to use #Html.Action to render your partialview. Consider below example.
#Html.Action("GetSearchPartial", "Controller", new {controller = "Women"})
//in the Women Edit View
#Html.Action("GetSearchPartial", "Controller", new {controller = "Man"})
//in the Man Edit View
Now write an action which returns ParialViewResult.
public PartialViewResult GetSearchPartial(string controller)
{
ViewBag.Controller=controller;
return PartialView("_SearchProduct");
}
in your _SearchProduct - PartialView get the ViewBag data and assign it as controller.
#{
string controller=ViewBag.Controller;
}
<div class="row">
<div class="col-md-6">
#using (Html.BeginForm("Edit", controller, FormMethod.Get))
{
<p>
Find by Product Id : #Html.TextBox("SearchString", ViewBag.CurrentFilter as string)
<input type="submit" value="Search" />
</p>
}
</div>
<div class="col-md-6">
<span style="color:green">#ViewBag.ProductName </span>
</div>
<span style="color:red"> #ViewBag.FindResult </span>
</div>
Let know if you face any issues

Try this way
#using (Html.BeginForm("Edit", #HttpContext.Current.Request.RequestContext.RouteData.Values["controller"].ToString(), FormMethod.Get)){}
instead of the actual location of the partial view. so dynamically set Man or Woman controller name

Related

Data annotation validation happening on page load in ASP.Net Core

I am facing the issue of data validation being executed on load of a new page even though it is clearly coming from a Get method. Is there something that's triggering the validations on page load?
I have a button on a view to add a new Student record in the new screen :
View :
<a type="button" id="btnAddStudent" href='#Url.Action("Details","Student")' class="btn btn-tertiary" title="Add Student">Add Student</a>
The controller code for the Details action method in Student Controller is as follows.
[HttpGet]
public ActionResult Details(StudentInfo model)
{
//This is populating the model parameters as expected.
helper.StudentInfo(ref model);
return View(model);
}
The view for the Details screen is as follows. The page loads but is throwing validation errors even though it's a Get method.
<form id="frmSubmit" asp-action="Details" asp-controller="Student" method="post">
<input type="hidden" asp-for="StudentId" />
<div class="row">
<div class="col-xs-12">
#Html.ValidationSummary("", new { #class = "alert alert-danger validation" })
</div>
</div>
<div class="row">
<div class="col-xs-12">
<div class="form-group">
<label asp-for="Name">*StudentName</label><br />
<input asp-for="Name" class="form-control" maxlength="100" placeholder="Enter student name..." />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<div class="form-group">
<label asp-for="AddressLine1"></label><br />
<input asp-for="AddressLine1" class="form-control" placeholder="Enter address..." />
<span asp-validation-for="AddressLine1" class="text-danger"></span>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<div class="form-group">
<label asp-for="AddressLine2"></label><br />
<input asp-for="AddressLine2" class="form-control" maxlength="100" />
<span asp-validation-for="AddressLine2" class="text-danger"></span>
</div>
</div>
</div>
<div class="box">
<div class="form-group pull-right">
<button type="submit" class="btn btn-primary" value="save"> Save</button>
</div>
</div>
Is there something I am doing wrong? I have verified that the debug control goes to the Get method.There's alos no on load scripts which are doing any sort of validation.
1.Your get method contains the model parameter, when the request hit the method it will judge the ModelState by default. And when you hit the get method by your shared <a>, it send request without any data, so the ModelState is invalid.
2.Default Tag helper displays ModelState's value not Model.
In conclusion, you will render the ModelState error although it is a get method.
Two ways you can resolve this problem. The first way is that you can add ModelState.Clear() before you return View:
public ActionResult Details(StudentInfo model)
{
ModelState.Clear(); //add this....
helper.StudentInfo(ref model);
return View(model);
}
The second way is do not add the model as parameter:
public ActionResult Details()
{
var model = new StudentInfo();
helper.StudentInfo(ref model);
return View(model);
}

How to pass the correct Model Diction type MVC

I am new as MVC 5, I have create a new project and I am setting up the login (With external login).
This is using the VIsual Studio 2013 MVC 5 Application template
So what is happening is when I click the button for a social media login I am getting an error of the wrong model being passed
The model item passed into the dictionary is of type
'WebPortal.Models.LoginViewModel', but this dictionary requires a
model item of type 'WebPortal.Models.ExternalLoginListViewModel'.
If you need the controls and model code let me know. But as I said this is the default code that came with the template. The only things I have been changing is the View at this point to change the look. And have posted the View Code below.
I think the issue is that since I am starting from the Layout page, the model is never being initiated since there is no model for the layout.... Again I am new so I am only guessing.
Here is the Partial path
"_Layout" -> "_SocialBar"(Partial View) -> "Login"(Partial View) -> "LoginPartial"(Partial View) -> "_ExternalLoginsList"(Partial View)
SocialBar (Partial View)
<div class="header-top dark ">
<div class="container">
<div class="row">
<div class="col-xs-3 col-sm-6 col-md-9">
...Some Code....
<!-- header-top-first end -->
</div>
<div class="col-xs-9 col-sm-6 col-md-3">
#Html.Partial("_Login")
</div>
</div>
</div>
</div>
Login Partial View page
#using Microsoft.AspNet.Identity
#if (Request.IsAuthenticated)
{
...Some Code...
}
else
{
...Some Code...
#Html.Partial("_LoginPartial")
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
LoginPartial View Code
#using WebPortal.Models
#model LoginViewModel
#using (Html.BeginForm("Login", "Account", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { role = "form" }))
{
#Html.AntiForgeryToken()
<form class="login-form margin-clear">
<div class="form-group has-feedback">
<label class="control-label">#Html.LabelFor(m => m.Email)</label>
#Html.TextBoxFor(m => m.Email, new { #class = "form-control" })
<i class="fa fa-user form-control-feedback"></i>
</div>
<div class="form-group has-feedback">
<label class="control-label">#Html.LabelFor(m => m.Password)</label>
#Html.PasswordFor(m => m.Password, new { #class = "form-control" })
<i class="fa fa-lock form-control-feedback"></i>
</div>
<div class="form-group has-feedback">
#Html.CheckBoxFor(m => m.RememberMe)
<label class="control-label">#Html.LabelFor(m => m.RememberMe)</label>
</div>
<input type="submit" value="Log in" class="btn btn-gray btn-sm" />
<span class="pl-5 pr-5">or</span>
#Html.ActionLink("Sign Up", "Register", "Account", null, new { #class = "btn btn-default btn-sm" })
<div class="form-group has-feedback">
Forgot your password?
</div>
#Html.Partial("../Account/_ExternalLoginsList")
</form>
}
ExternalLogin List Code
#model WebPortal.Models.ExternalLoginListViewModel
#using Microsoft.Owin.Security
#{
var loginProviders = Context.GetOwinContext().Authentication.GetExternalAuthenticationTypes();
if (loginProviders.Count() == 0)
{
<span class="text-center">No External Logins</span>
}
else
{
<span>Login with&nbsp&nbsp&nbsp
#foreach (AuthenticationDescription p in loginProviders)
{
switch (#p.AuthenticationType)
{
case "Facebook":
<button type="submit" class="btn btn-xsm facebook" id="#p.AuthenticationType" name="provider" value="#p.AuthenticationType"><i class="fa fa-facebook"></i></button>
break;
case "Twitter":
<button type="submit" class="btn btn-xsm twitter" id="#p.AuthenticationType" name="provider" value="#p.AuthenticationType"><i class="fa fa-twitter"></i></button>
break;
case "Google":
<button type="submit" class="btn btn-xsm googleplus" id="#p.AuthenticationType" name="provider" value="#p.AuthenticationType"><i class="fa fa-google-plus"></i></button>
break;
case "Microsoft":
<button type="submit" class="btn btn-xsm microsoft" id="#p.AuthenticationType" name="provider" value="#p.AuthenticationType"><i class="fa fa-windows"></i></button>
break;
default:
<button type="submit" class="btn btn-xsm" id="#p.AuthenticationType" name="provider" value="#p.AuthenticationType">#p.AuthenticationType.ToString()</button>
break;
}
}
</span>
}
}
When you do #Html.Partial() and don't provide it a model, it uses the current (or parent, if you want to think of it that way) model instead. So when you do
#Html.Partial("../Account/_ExternalLoginsList")
Without the second parameter to specify the model, it provides the current one. You should be providing a view model to the partial like so:
#Html.Partial("../Account/_ExternalLoginsList", externalLoginsViewModel)
Otherwise you'll provide the current one, which is not the same type that is expected by the partial.
The ExternalLoginList partial expects a model to be passed to it.
#model WebPortal.Models.ExternalLoginListViewModel
You need to pass the model in here:
#Html.Partial("../Account/_ExternalLoginsList")
Like this:
#Html.Partial("../Account/_ExternalLoginsList", new ExternalLoginListViewModel())
OR
Put the partial's model in the parent's model
public class LoginViewModel
{
public ExternalLoginListViewModel externalLoginListViewModel;
}
and pass it to the partial.
#Html.Partial("../Account/_ExternalLoginsList", externalLoginListViewModel)
OR
I don't see any references to the model in the ExternalLoginList partial so you can probably just delete this line:
#model WebPortal.Models.ExternalLoginListViewModel

Error Post Method with Partial View

I have the following error when trying to post a partial view form on my page:
An exception of type 'System.Web.HttpException' occurred in System.Web.dll but was not handled in user code
Additional information: Error executing child request for handler 'System.Web.Mvc.HttpHandlerUtil+ServerExecuteHttpHandlerAsyncWrapper'.
The error is related to the line below within the main view
The Main View is:
#{
ViewBag.Title = "Home Page";
}
<div class="jumbotron">
#Html.ActionLink("Create a Club", "SelectClubType", "Club")
</div>
<div>
#Html.Action("SelectClubType", "Club")
</div>
<div class="row">
<p>something here</p>
</div>
The Partial View is:
#model GRCWebApp.ViewModels.SelectClubTypeViewModel
#{
Layout = null;
}
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-group">
<div class="row col-md-12">
<h3>Create a new Club - Select the type</h3>
</div>
<div class="row col-md-12">
<div class="col-md-3">
#Html.DropDownListFor(model => model.SelectedClubTypeId, new SelectList(Model.ClubTypes, "ClubTypeId", "ClubTypeName"), new { #class = "form-control" })
</div>
<div class="col-md-2 ">
<input type="submit" value="Create" class="btn btn-success" />
</div>
</div>
</div>
}
The Post Method:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult SelectClubType(SelectClubTypeViewModel model)
{
int id = model.SelectedClubTypeId;
return RedirectToAction("Create", new { id = id });
}

Calling an Action in MVC when redirected from a partial view

I'm having this issue in which I have a log in screen and a register screen in different cshtml files, but the register view is called as a #Html.Partial. The code in the log in screen is as follows:
<div class="panelLogIn left #if (ViewBag.register) { Write("hidden"); }">
#using (Html.BeginForm()) {
<div>
<div class="validationMessage" style="padding-bottom:10px;">#Html.ValidationMessage("loginFailed")</div>
<div class="field">
<span class="textOverField absolute em1-2" style="top:6px;left:4px;">User</span>
#Html.TextBoxFor(a => a.UserName, new { #class = "textField" }) <div class="absolute validationMessage">#Html.ValidationMessageFor(u => u.UserName)</div>
</div>
<div class="field relative">
<span class="textOverField absolute em1-2" style="top:6px;left:4px;">Password</span>
#Html.PasswordFor(a => a.Password, new { #class = "textField" }) <div class="absolute validationMessage">#Html.ValidationMessageFor(u => u.Password)</div>
</div>
<div class="em0-9" style="margin-bottom: 20px;">
<input class="submitButton cursorHand" style="margin-top: 10px;" type="submit" value="Enter" />
</div>
<div class="em0-9">
<span class="guestLink bold linkBlue underline cursorHand">Register Free</span>
</div>
</div>
}
</div>
<div class="panelGuest left #if (!ViewBag.register) { Write("hidden"); }">
#Html.Partial("RegisterUser", Model.NewUser)
</div>
And the Register view is as follows:
#using (Html.BeginForm("Register", "Account"))
{
/* The text boxes and form elements */
<div class="em0-9" style="margin-bottom:20px;">
<input class="submitButton cursorHand" style="margin-top:10px;" type="submit" value="Register" />
</div>
}
Basically, the issue is that when I try to Register a new user, it redirects me to localhost/Account/Register and when I go back to the LogIn screen (which is in the same view) I can't call any other action aside from the register one.
Any help with this will be greatly appreciated.
Try fully specifying the action of your first Html Form, as you have done in the Partial:
#using (Html.BeginForm("Index", "Account")) {
//
}
You should probably have a different view for resgister. It looks like you have one view which contains the login box(username / password fields) & also new user registration fields.
but the register view is called as a #Html.Partial
If you are familiar with user controls in the web forms programming model, Html partials would be somewhat similar to user controls.
So code in login screen would be just
<div class="panelLogIn left #if (ViewBag.register) { Write("hidden"); }">
#using (Html.BeginForm()) {
<div>
<div class="validationMessage" style="padding-bottom:10px;">#Html.ValidationMessage("loginFailed")</div>
<div class="field">
<span class="textOverField absolute em1-2" style="top:6px;left:4px;">User</span>
#Html.TextBoxFor(a => a.UserName, new { #class = "textField" }) <div class="absolute validationMessage">#Html.ValidationMessageFor(u => u.UserName)</div>
</div>
<div class="field relative">
<span class="textOverField absolute em1-2" style="top:6px;left:4px;">Password</span>
#Html.PasswordFor(a => a.Password, new { #class = "textField" }) <div class="absolute validationMessage">#Html.ValidationMessageFor(u => u.Password)</div>
</div>
<div class="em0-9" style="margin-bottom: 20px;">
<input class="submitButton cursorHand" style="margin-top: 10px;" type="submit" value="Enter" />
</div>
<div class="em0-9">
<span class="guestLink bold linkBlue underline cursorHand">Register Free</span>
</div>
</div>
}
</div>
You can have a separate register view in which you can include your register partial.
Hope this helps.

MVC Retrieve Multi Entry from View in Controller

this is my controller:
public ActionResult Create() {
Number newNumber = new Number();
return View(newNumber);
}
and View :
#model PhoneBook.Models.Number
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
<script src="../../Scripts/jQuery.AddNewNumber.js" type="text/javascript"></script>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
#Html.HiddenFor(model => model.Contact.Id)
<fieldset>
<legend>Number</legend>
<div class="TargetElements">
<div class="editor-label">
#Html.LabelFor(model => model.PhoneNumber)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.PhoneNumber)
#Html.ValidationMessageFor(model => model.PhoneNumber)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.NumberKind)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.NumberKind.Title, NumberKinds)
</div>
</div>
<p>
<input class="AddNew" value="Add New" type="button" /></p>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
By press AddNew button (use jQuery AddNewNumber.js) new input+DropDown Added to form in client side. But there is a problem in retrieve values, When I have one entry element(include input+DropDown) I can retrieve values like the following in post of my controller:
[HttpPost]
public ActionResult Create(Number NewNumber, FormCollection collection) {
db.Numbers.Add(NewNumber);
db.SaveChanges();
return RedirectToAction("Index")
}
But when there is multi-entry how can I retrieve values and add them to DataBase?
Use by the name of element like this:
string[] PhoneNumbers = collection.GetValues("PhoneNumber");
You want all of your input elements to have the same name. Then in your POST action method, the parameter would be List. Here is an example:
Model Binding to a List of objects

Categories

Resources