C# MVC replace one Partial View with another - c#

I'm building a website using MVC where i want it to have a small box on the head Nav-bar where the user can log in to his account. The head Nav-bar is a layout page shared with all the views i have and the Partial view of the login is rendered in the layout.
this is the layout with the partial view placement:
<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header">
#Html.ActionLink("חנות השיגועים של האחים וויזלי", "Master", "Home", new { area = "" }, new { #class = "navbar-brand" })
</div>
<ul class="nav navbar-nav">
<li>#Html.ActionLink("בית", "Master", "Home")</li>
<li>#Html.ActionLink("אודות", "About", "Home")</li>
<li>#Html.ActionLink("צור קשר", "Contact", "Home")</li>
<li>#Html.ActionLink("סל קניות", "Cart", "Home")</li>
<li>#Html.ActionLink("פרופיל", "UserProfile", "Home")</li>
<li>#Html.ActionLink("הרשמה", "Register", "Account")</li>
</ul>
#*<ul class="nav navbar-nav navbar-right">
<li>*#
<div id="PartialPlace">
#Html.Partial("_LoginPartial")
</div>
#*</li>
</ul>*#
</div>
</nav>
<div class="container body-content">
#RenderBody()
<img src="~/Assets/Site_Background.jpg" alt="Weasly Shop" id="BkgImage" class="bg"/>
<hr />
<footer>
<p>© #DateTime.Now.Year - My ASP.NET Application</p>
</footer>
</div>
this is the Login partial code:
<form method="post" id="LoginFloat" action="/account/login">
<div class="container">
<label><b>Username</b></label>
<input type="text" placeholder="Enter Username" name="UserName" required>
<label><b>Password</b></label>
<input type="password" placeholder="Enter Password" name="Password" required>
<button type="submit" class="btn btn-primary">Login</button>
#*#Ajax.ActionLink("Login", "Login", "Account", new AjaxOptions() { UpdateTargetId = "divToUpdate" }, new { #class = "btn btn-primary" })*#
<input type="checkbox" checked="checked"> Remember me
</div>
and this is the action:
[HttpPost]
public ActionResult Login(string UserName, string Password)
{
using (AspStoreDBEntities1 db = new AspStoreDBEntities1())
{
if (ModelState.IsValid)
{
foreach (var user in db.Users)
{
if (user.UserName == UserName && user.Password == Password)
{
FormsAuthentication.SetAuthCookie(UserName, true);
return PartialView("_LogedInPartial");
}
}
}
return View();
}
}
What i want to do is when the user press the Login Button in the Login partial in the layout only the partialView will refresh and will show the user this partial view where he could post an ad:
<div class="container">
<div class="jumbotron" id="LoginFloat">
<h5>Hello #Model.UserName</h5>
<button class="btn btn-warning" onclick="">Advertise!</button>
<br />
<input type="submit" name="LogOff" value="LogOff" />LogOff
</div>
I tried using Ajax.Actionlink with the replacement action, but i couldn't figure out how to use it. Should i use it in the layout page or in the Login partialView or where?

Related

Failed to send model to a controller in asp mvc?

So this is my edit controller:
namespace WebFront_End.Controllers
{
public class EditController : Controller
{
private ActiviteitContainer AC = new(new ActiviteitenMSSQLDAL());
public IActionResult Index(ActiviteitVM activiteit)
{
return View(activiteit);
}
public IActionResult Return(ActiviteitVM activiteit)
{
AC.UpdateActivityWithDayOnly(activiteit.ToActiviteit(), HttpContext.Session.GetInt32("UserId").Value);
return RedirectToAction("Index", "Home");
}
}
}
this is the home page where the edit button should send the model to the edit view:
#model UserVM
#using WebFront_End.Models
#{
ViewData["Title"] = "Home Page";
}
<h1>Hello #Model.GetFullName()</h1>
<div class="container border">
<div class="row">
<div class="col AC_header">
<p>Type</p>
</div>
<div class="col AC_header">
<p>Title</p>
</div>
<div class="col AC_header">
<p>Start Time</p>
</div>
<div class="col AC_header">
<p>End Time</p>
</div>
</div>
#foreach (ActiviteitVM a in Model.activiteiten)
{
<div class="row">
<div class="col AC">
<p>#a.Type</p>
</div>
<div class="col AC">
<p>#a.Name</p>
</div>
<div class="col AC">
<p>#a.Date</p>
</div>
<div class="col AC">
<p>#a.Date</p>
</div>
<div class="col">
</div>
<form asp-controller="Edit" asp-action=Index asp-route-activiteit="#a" method="post">
<input type="submit" value="Edit" class="btn btn-primary" />
</form>
</div>
}
</div>
this is my Edit view which gets it model from the home view:
#model ActiviteitVM
#{
ViewData["Title"] = "Index";
}
<form asp-controller="Edit" asp-action=Return method="post">
<h1>Index</h1>
<div>
<label for="Name">Name</label>
<input asp-for=Name value= "#Model.Name" class="form-control" />
</div>
<div>
<label for="Type">Type</label>
<input asp-for=Type value="#Model.Type" class="form-control" />
</div>
<div>
<label for="Description">Description</label>
<input asp-for=Description value="#Model.Description" class="form-control" />
</div>
<div>
<label for="Date">Date</label>
<input asp-for=Date value ="#Model.Date.Date.ToString("YYYY-MM-DD")" class="form-control" />
</div>
<input type="submit" value="Confirm" class="btn btn-primary" />
</form>
The fields are empty so that means the model is empty, which is weird because there is a model needed to get to the page. Which means its sending a empty model. I can't see the problem maybe in the foreach loop?

Add a search bar in asp net mvc

I need to add a search bar on my index page, and the result of the research will be show on another page.
What I've tried:
The view
<form class="row contact-form rounded-pill link no-gutters" id="contact-form-data">
#using (Html.BeginForm("RechercheResto", "Client", FormMethod.Post))
{
#Html.AntiForgeryToken()
<div class="col-12 col-lg-8 d-inline-block d-lg-flex align-items-center">
<div class="form-group">
<label><i class="lni lni-restaurant" aria-hidden="true"></i></label>
<input type="text" name="nomResto" placeholder="Nom du restaurant" class="form-control">
</div>
</div>
<div class="col-12 col-lg-4">
<i class="fa fa-spinner fa-spin mr-2 d-none" aria-hidden="true"></i>
<input type="submit" class="btn main-btn rounded-pill w-100 h-100 contact_btn" value="Rechercher le restaurant" />
</div>
}
</form>
The controller
[ValidateAntiForgeryToken]
public ActionResult RechercheResto(string nomResto)
{
var restoList = from r in db.Restaurants select r;
if (!string.IsNullOrEmpty(nomResto))
{
restoList = restoList.Where(r => r.name.Contains(nomResto));
}
return View(restoList.ToList());
}
At the time of returning View(restoList.ToList()) you can add viewname in first parameter and second will be your result.ToList().
Thanks for your help. I've just find the solution. The problem was the I put before the BeginForm.
The working code look like that
#using (Html.BeginForm("RechercheResto", "Client", FormMethod.Post, new { #class= "row contact-form rounded-pill link no-gutters"}))
{
#Html.AntiForgeryToken()
<div class="col-12 col-lg-8 d-inline-block d-lg-flex align-items-center">
<div class="form-group">
<label><i class="lni lni-restaurant" aria-hidden="true"></i></label>
<input type="text" name="nomResto" placeholder="Nom du restaurant" class="form-control">
</div>
</div>
<div class="col-12 col-lg-4">
<i class="fa fa-spinner fa-spin mr-2 d-none" aria-hidden="true"></i>
<input type="submit" class="btn main-btn rounded-pill w-100 h-100 contact_btn" value="Rechercher le restaurant" />
</div>
}

ASP .NET MVC dynamically created fields not bind to FormCollection

I created a Partial Razor view with dynamically created fields:
for (int i = 0 ; i < atr.Count; i++)
{
<div class="col-md-12 panel panel-default sx-box-shadow-on-hover">
<div class="panel-heading">
<h2 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="##string.Format("{0}{1}", "collapse", #atr[i].Id)" aria-expanded="true">
#atr[i].Label
<span class="caret"></span>
</a>
</h2>
</div>
<div id=#string.Format("{0}{1}", "collapse", #atr[i].Id) class="col-md-12 panel-collapse collapse" aria-expanded="true">
<form>
<div class="form-group">
#switch (atr[i].AtrType)
{
case "TXT":
case "NUM":
<input id=#atr[i].Id class="form-control margin5" name=#atr[i].Name type="text" />
break;
case "CHB":
<input class="form-control margin5" name=#atr[i].Name type="checkbox" />
break;
case "DTP":
#(Html.Kendo().DatePicker()
.Name(#atr[i].Name)
.Value(DateTime.Now)
.HtmlAttributes(new { style = "margin-top: 5px; width:100% !important", title = #atr[i].Name })
)
break;
case "WTXT":
<textarea name=#atr[i].Name , rows="3"></textarea>
break;
}
</div>
</form>
</div>
</div>
}
Partial view is placed in other view with static fields and button. When I make POST action using button, in FormCollection I have only values from static fields. I can't bind this field's to Model because user can add or delete them in any moment. Every dynamic field created in partial view has it's own Id and Name. What am I missing here?
Post Action:
[HttpPost]
[Authorize]
public ActionResult Search(FormCollection form)
{
//
}
Main Razor Page:
#using (Html.BeginForm("Search", "Home", FormMethod.Post))
{
<div class="col-md-12 panel panel-default sx-box-shadow-on-hover">
<div class="panel-heading">
<h2 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#searchCollapse" aria-expanded="true">
Search options
<span class="caret"></span>
</a>
</h2>
</div>
<div id="searchCollapse" class="col-md-12 panel-collapse collapse in" aria-expanded="true">
<div class="form-group">
<label class="col-md-12 fontBold margin5">Document type:</label>
#(Html.Kendo().DropDownList()
.Name("DocumentTypesDropDownList")
.DataTextField("Name")
.DataValueField("Id")
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetDocTypes", "Home");
});
})
.Events(e =>
{
e.Change("docTypeOnChange");
})
.HtmlAttributes(new { style = "margin-top: 5px; width:100% !important", title = "DocumentTypesDropDownList" })
)
<button id="SearchButton" class="btn btn-primary form-control margin5">Search</button>
<div id="searchPanelDiv">
#{
Html.RenderPartial("SearchPanel");
}
</div>
</div>
</div>
</div>
}
Request body looks like this:
DocumentTypesDropDownList=1&Identificator=1234
Parameters from dynamic fields are missing.
I think if you place this:
[HttpPost]
[Authorize]
public ActionResult Search(FormCollection form)
{
var fields = new List<(string, string)>();
foreach (var item in Request.Form)
{
fields.Add((item.Key, item.Value));
}
// do some other stuff
}
in your controller, you are able to read all the fields located in your body request, no matter if they were added dynamically or not.
Nested forms are unsupported in HTML.
If you remove the <form> and </form> tags from the partial view you should be able to capture the dynamic inputs from the FormCollection that is created on the main page by the #using (Html.BeginForm.

Partial View Not Rendering Inside View

I have a partial view inside another partial view which, when first running the application loads as expected, but when you click to reload the view to push a model into it, it then renders as it's own completely separate view as if it weren't a partial.
I'm calling it inside an Ajax Form like so (On the Action link click, the _GetSearchModal method):
<div id="modelSearch">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">
<i class="fa fa-search"></i> Search by Model / Manufacturer
</h3>
</div>
<div class="panel-body">
#using (Ajax.BeginForm("_GetSearch", "Home", new AjaxOptions() {UpdateTargetId = "modelSearch"}))
{
#Html.AntiForgeryToken()
<div class="input-group">
#Html.TextBox("search", null, new {id = "name", #class = "form-control", placeholder = "Please enter a manufacturer or model"})
<span class="input-group-btn">
<button id="search" class="btn btn-default" type="submit"><i class="fa fa-search"></i></button>
</span>
</div>
if (Model != null)
{
<div id="searchResults" class="fade-in two">
#foreach (var s in Model)
{
<div class="result">
#switch (s.ResultType)
{
case "Man":
#s.Manufacturer
break;
case "Mod":
#Html.ActionLink(s.Manufacturer + Html.Raw(s.Model), "_GetSearchModal", "Home", new {id = s.MachineId}, new {toggle = "modal", data_target = "#MachineModal"})
<img src="~/Images/General/Tier/#(s.TierId).png" alt="Tier #s.TierId"/>
break;
}
</div>
}
</div>
}
}
</div>
</div>
</div>
<!-- Product Modal -->
<div class="modal fade" id="MachineModal" tabindex="-1" role="dialog" aria-labelledby="MachineModalLabel">
#Html.Partial("_SearchModal", new MachineModal())
</div>
And the view itself should load a different view model (MachineModal):
#model SpecCheck.Portals.Web.UI.ViewModels.MachineModal
#if (Model != null)
{
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="MachineModalLabel">#Model.Manufacturer #Model.Model</h4>
</div>
<div class="modal-body">
<div class="row">
<div class="col-md-6">
<img src="~/Images/#Model.Manufacturer/logo.png" alt="#Model.Manufacturer" /><br />
Wiki
</div>
<div class="col-md-6">
#Model.Catagory1 | #Model.Category2<br /><br />
<span class="modal-em">Region: </span> #Model.Region<br />
<span class="modal-em">Status: </span>#Model.Status<br />
<span class="modal-em">Spec Date: </span>#Model.SpecDate
</div>
</div>
</div>
<div class="modal-footer">
View
Quick Compare
Compare
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
}
And the action to do this in the "Home Controller" is:
public ActionResult _GetSearchModal(string machineId)
{
using (var db = new SpecCheckDbContext())
{
MachineModal machine = new MachineModal();
var searchHelper = new SearchHelper(db);
//Get Machine Details
var dbResults = searchHelper.SearchModal(Convert.ToInt32(machineId));
machine.Model = dbResults.Model;
machine.Catagory1 = dbResults.Catagory1;
machine.Category2 = dbResults.Category2;
machine.Manufacturer = dbResults.Manufacturer;
machine.Region = dbResults.Region;
machine.SpecDate = dbResults.SpecDate;
machine.Status = dbResults.Status;
machine.MachineId = dbResults.MachineId;
machine.ManufacturerId = dbResults.ManufacturerId;
var model = machine;
return PartialView("_SearchModal", model);
}
}
First thing I checked was the scripts, they're all in place when the layout page loads so it's not a script issue. Not sure what to change to even try at this point so any suggestions welcome.
In the ajax form:
_GetSearch => _GetSearchModal(name of the action)
Try to return machine to the partial view? Maybe see in the View hierarchy, is there is second _SearchModal partial view, that gets returned?

Update _Layout for different type of users

I'm using the MVC template on Asp.net MVC 4, and I have a UserProfile(t class with the UserType(this field receive only 2 values, "Ouvinte" and "Musico") field, that works like roles in application, right?
My idea is, make a verification on _Layout.cshtml to know what is the UserType that are logged on application and modify the navbar on top.
THIS IS MY NAVBAR ON _Layout
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">#Html.ActionLink("your logo here", "Index", "Home")</a>
</div>
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li>#Html.ActionLink("Home", "Index", "Home")</li>
<li>#Html.ActionLink("Usuario", "Usuario", "Home")</li>
<li>#Html.ActionLink("Musico", "Musico", "Home")</li>
</ul>
<ul class="nav navbar-nav navbar-right">
#if (!Request.IsAuthenticated){ //IF USER IS NOT LOGGED.
<li>#Html.ActionLink("Register", "Register", "Account")</li>
<li>#Html.ActionLink("Log In", "Login", "Account")</li>
}
else //DO A ELSEIF HERE IF THE USER HAS THE USERTYPE Musico
{
<li>#Html.ActionLink("Manage Account", "Manage", "Account")</li>
<li>#using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm" })) {
#Html.AntiForgeryToken()
Log off}</li>
} //ANOTHER ELSE HERE TO VERIFY IF THE USER HAS USERTYPE Ouvinte
</ul>
</div><!--/.nav-collapse -->
</div>
</div>
My doubt is, how can i call the userProfile here to do these validation?

Categories