I have a View and I want to render a specific partial depends on the size of the window.
The View looks:
#using (Html.BeginForm("Index", "search", FormMethod.Get))
{
#Html.Partial("_Search")
<div class="searchmob" style="display: none;">
<h1>mobile</h1>
#Html.Partial("_SearchComponentMobile")
</div>
}
by default the div searchmob is invisible and when making the screen smaller the div appears (it works)
The problem both of the partials contain textbox #Html.TextBox with the same name so when submitting from _SearchComponentMobile it sends the _Search's textbox value.
Is it possible to render specific partial when required.
I used in one of my views the below code but in the above saturation it is related to a css, was hoping something similar can be accomplished:
#{
var act = ViewContext.RouteData.Values["action"].ToString().ToUpper();
}
#if (#act == "INDEX")
{
//render a partial view otherwise it doesn't
}
I am using bootstrap maybe this can also help me?
Have you tried using the DisplayModeProviders built into MVC?
Essentially the view engine will look for 'overrides' of your views if the request is coming from a mobile platform.
So your main view would look like:
#using (Html.BeginForm("Index", "search", FormMethod.Get))
{
#Html.Partial("_Search")
}
Then rename your _SearchComponentMobile.cshtml to _Search.mobile.cshtml and let MVC take care of the rest (note you'll need to move you <div class="searchmob"> into the partial if it has styling associated with it)
More info here if you need it:
http://www.asp.net/mvc/overview/older-versions/aspnet-mvc-4-mobile-features
http://www.hanselman.com/blog/MakingASwitchableDesktopAndMobileSiteWithASPNETMVC4AndJQueryMobile.aspx
EDIT
Otherwise repeat the form inside the mobile layout....
#using (Html.BeginForm("Index", "search", FormMethod.Get))
{
#Html.Partial("_Search")
}
<div class="searchmob" style="display: none;">
<h1>mobile</h1>
#using (Html.BeginForm("Index", "search", FormMethod.Get))
{
#Html.Partial("_SearchComponentMobile")
}
</div>
Related
I have a razor page that uses T4template. Here is my razor code:
#model ResearchViewModel
<form method="POST" action=">
...
#if (!Model.IsFinalized)
{
using (Html.BeginForm(MVC.Research.ActionNames.Reject, MVC.Research.Name, null, FormMethod.Post, new { #id = "RejectForm" }))
{
#Html.AntiForgeryToken()
#Html.HiddenFor(model => model.Id)
}
using (Html.BeginForm(MVC.Research.ActionNames.Accept, MVC.Research.Name, null, FormMethod.Post, new { #id = "AcceptForm" }))
{
#Html.AntiForgeryToken()
#Html.HiddenFor(model => model.Id)
}
}
...
</form>
The problem is that when the razor rendering this page, it cannot rendering first form !! I tried to change the sequence of these forms, and found that always the first form is not rendered. I Also tried to separate these forms using the partialview but the problem still exist. Does anyone knows that what's happening ?
You are trying to nest multiple forms and you can't do that. See this link for an explanation: Can you nest html forms?
You need to remove your starting HTML
<form method="POST" action=">
because you can't have other forms inside them. I would guess that closing tag of your first form created by razor Html helper is closing this tag, so you can see the other form created by second razor Html helper
First off I am new to MVC, I was a webforms guy...
I want to show my login control on my home/index page, but no matter what I do I run in to errors. I have tried various techniques and have gotten many errors with each technique, so I wont list them all here.
Right now I have it set that if Request.IsAuthenticated then show the username else show the login form. But the form is obviously looking at the home controller and nothing happens when I submit the login.
Any advice would be much appreciated. I have been dabbling for days on this.
Thanks :)
Here is the Code:
'#{
ViewBag.Title = "MyApp";
}
<p>Code for main Index Page here</p>
#model Application.Models.LoginModel
#{
ViewBag.Title = "Log in";
}
#if (Request.IsAuthenticated) {
<text>
Hello, #Html.ActionLink(User.Identity.Name, "Manage", "Account", routeValues: null, htmlAttributes: new { #class = "username", title = "Manage" })!
#using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm" })) {
#Html.AntiForgeryToken()
Log off
}
</text>
} else {
<section id="loginForm">
<h2>Use a local account to log in.</h2>
#using (Html.BeginForm(new { ReturnUrl = "RedirectToAction" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>Log in Form</legend>
<ol>
<li>
#Html.LabelFor(m => m.UserName)
#Html.TextBoxFor(m => m.UserName)
#Html.ValidationMessageFor(m => m.UserName)
</li>
<li>
#Html.LabelFor(m => m.Password)
#Html.PasswordFor(m => m.Password)
#Html.ValidationMessageFor(m => m.Password)
</li>
<li>
#Html.CheckBoxFor(m => m.RememberMe)
#Html.LabelFor(m => m.RememberMe, new { #class = "checkbox" })
</li>
</ol>
<input type="submit" value="Log in" />
</fieldset>
<p>
#Html.ActionLink("Register", "Register", "Account") if you don't have an account.
</p>
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
</section>
}
'
you have to modify your form like this:
#using (Html.BeginForm("Login","Account",FormMethod.Post, new { ReturnUrl = ViewBag.ReturnUrl }))
the key is the "Login","Account" part, that tells the form to post the data to the login action of the account controller instead of the home controller. I fought with the same thing for a few hours then figured it out.
if the data does not post to the account controller (the controller that actually validates the username and password and logs the user in) it will never try to log them in.
reason is :
by default in the routeconfig.cs class sends any links or forms that do not specify an action and controller send all stuff to the Index action of the Home controller.
Hope this helps
You should use a Child Action:
In your controller:
[ChildActionOnly]
public ActionResult LoginForm()
{
return View("_LoginFormPartialViewHere");
}
Then in your homepage view:
#{ Html.RenderAction("LoginForm"); }
In your partial view for your login form, you can strongly-type the view for your login view model, but make sure to specify a different post action for your form than the default "postback" model. This action will handle the login and only the login (so not your homepage action).
Your problem here is that you are attempting to write code without actually understanding what it does. Without understanding what it does, you are simply left randomly changing things hoping to find something that works. This is a very poor way to write software.
Your problem is rooted in the fact that you don't understand that MVC is merely generating HTML, and without understanding what that HTML is supposed to be doing, you have little hope of randomly figuring this out.
First, MVC has no concept of a "login control". They're just HTML form fields, and they sit within an HTML form element. Those form fields are posted to your controller using standard HTML, which means you have to ensure your form action method is correct, and that the action url is correct.
Secondly, when those form fields are posted, you have to have an action method that will receive the post. If that action method is not the same as the action method used in the GET, then you will have to tell the BeginForm() helper where to post to.
In MVC, you can't think like Webforms and just assume everything gets done for you. You have to do everything yourself, and make sure every link, every action, every selector, every bit of javascript, etc.. is all correct. This is more work than WebForms, but it's also more powerful and more efficient.
I'm trying to create a single view which allows the user to see the currently listed items using the index view model and then also allows the user to create a new item using a seperate create view model
So I've got two viewModels
-IndexFunkyThingsViewModel
-CreateFunkyThingViewModel
In essence I've got a main view:
#model IndexFunkyThingsViewModel
#foreach (var item in Model.FunkyThings)
{
/*Indexy stuff*/
}
/*If create item*/
#if (Model.CreateFunkyThing)
{
#Html.Partial("_CreateFunkyThingPartial", new CreateFunkyThingViewModel());
}
Then in my partial view I have
#model CreateFunkyThingViewModel
#using (Html.BeginForm(MVC.FunkyThings.CreateFunkyThing(Model)))
{
#Html.ValidationSummary(true)
<fieldset>
<legend>Create FunkyThing</legend>
#Html.EditorForModel();
<p>
<input type="submit" class="button green" value="CreateFunkyThing" />
</p>
</fieldset>
}
Finally in the controller I have:
[HttpPost]
public virtual ActionResult CreateFunkyThing(CreateFunkyThingViewModel createFunkyThingViewModel)
{
..
}
This all seems to compile happily and when I go to the view it works so far as displaying the create fields and such like. However when I then hit the submit button the controller receives no data. The ActionResult is called however in the debugger the createFunkyThingViewModel parameter is null when called by the submit button.
What am I doing wrong?
When posting to your controller, you're not sending the model down to it. Use this:
#using (Html.BeginForm("CreateFunkyThing", "ControllerName", FormMethod.Post))
then remove the p tags from around the button, and don't use anything with it.
The paragraph tags have a tendency to group the button separately from a form even if they are in the same outer container.
Suppose I have a simple search form with a textbox. And upon submitting the form I send the contents of the textbox to a stored procedure which returns to me the results. I want the results to be displayed on the same page the form was, except just below it.
Right now I'm doing the following but it's not working out exactly the way I want:
"Index" View of my SearchController
#using (Html.BeginForm("SearchResults", "Search", FormMethod.Post, new { #class = "searchform" }))`{
<fieldset>
<legend>Name</legend>
<div class="editor-label">
#Html.Label("Search")
</div>
<div class="editor-field">
#Html.TextBox("Name")
</div>
<input type="submit" value="Search" class="formbutton" />
</fieldset>
#{ Html.RenderPartial("SearchResults", null);
This is my "SearchResults" View:
#model IEnumerable<MyProject.Models.spSearchName_Result>
<table>
#foreach (var item in Model)
{
<tr>
<td>
#item.Name
</td>
</tr>
}
</table>
This is my Controller:
// GET: /Search/SearchResult
[HttpPost]
public ActionResult SearchResult(FormCollection collection)
{
var result = myentity.spSearchName(collection["Name"]);
return PartialView("SearchResults", result);
}
I can only seem to get the results to display on an entirely new page (not being embedded as a partial view), or I get an error when I load the search page because there are no results (since I hadn't searched yet).
Is there any better way to achieve what I'm trying to do? I feel like I'm going against some of the best practices in MVC.
You could return the results in a ViewData object then only show on the view it if is not null.
Very similar to this question MVC 3 form post and persisting model data
For this instance it looks like you are not passing the results to your partial view. Try this?
#{ Html.RenderPartial("SearchResults", Model.Results);
Since you are not persisting your search information using a model, the search information will be lost when the search form is posted.
Given your design and stated goal, it would be best to convert the form in your Index view into an Ajax form, then your controller can send your partial view back to populate a div below your Ajax form.
counsellorben
I have a partial view in MVC that goes something like:
<div id="comments">
...
</div>
Inside that div there's a form that calls a controller using AJAX and gets back that same partial view. The problem is that the results of calling the view replaces the contents of the div, not the whole div, and I end up with:
<div id="comments">
<div id="comments">
...
</div>
</div>
The only solution I can think about with my week of experience in ASP.Net MVC and AJAX is to put the div outside the partial view and make the partial view only contain the inside part, but then the form would refer to an id outside the view where the form is located breaking the little encapsulation I have left there. Is there any better solution?
The unobtrusive Ajax library that ships with .NET MVC 3 uses callbacks that are based on the four callbacks from jQuery.ajax. However, the InsertionMode = InsertionMode.Replace from the Ajax.BeginForm method does not result in jQuery's replaceWith being called. Instead, .html(data) is used to replace the contents of the target element (and not the element itself).
I have described a solution to this problem on my blog:
http://buildingwebapps.blogspot.com/2011/11/jquerys-replacewith-and-using-it-to.html
Are you using an AjaxHelper.Form or jQuery. If you are using jQuery, have you tried using replaceWith()? Using AjaxHelper are you using AjaxOptions { InsertionMode = InsertionMode.Replace }? I would think that using either you would be able to replace the entire DIV with the results from the partial view.
Using
AjaxOptions { UpdateTargetId = "myDiv", InsertionMode = InsertionMode.Replace }
should replace the whole content of '#myDiv' element, as tvanfosson says. Your problem is where is '#myDiv' located. Here's an example:
<div id="myDiv">
<% Html.RenderPartial("MyPartialView"); %>
</div>
where MyPartialView is:
<div id="comments">
<% using (Ajax.BeginForm(new AjaxOptions() { UpdateTargetId = "myDiv", InsertionMode = InsertionMode.Replace } )) {%>
...
<input type="submit" value="Submit comment" />
<% } %>
</div>
If you include '#myDiv' div inside the partial view, it will be rendered right after receiving the response (together with its content), and then it's content will be replace with the response which is the same partial view (including its own '#myDiv' div), and that's why you always end up with 2 nested divs.
You should always use a container for your partial views and then set the UpdateTargetId to the container id.
Edit: I updated the code to represent the exact situation you describe in your question.
I had this same problem in Asp.Net MVC 5.
I did not want the PartialView to have some knowledge about what div it might be contained within, so I did not accept that work around.
Then, I noticed the other answers referring to ReplaceWith and found the simple solution:
InsertionMode = InsertionMode.ReplaceWith
Now, the mvc partial view can completely replace itself with the ajax helpers without having any dependencies on names outside itself.
Your should try with jQuery too (from my answer on MS MVC form AJAXifying techniques):
<script type="text/javascript">
$(document).ready(function() {
ajaxify($('div#comments'));
});
function ajaxify(divWithForm) {
var form = $('form', divWithForm);
$(':submit', form).click(function (event) {
event.preventDefault();
$.post(form.attr('action'), form.serialize(),
function(data, status) {
if(status == 'success') {
var newDivWithForm = $(data);
ajaxify(newDivWithForm);
divWithForm.after(newDivWithForm).remove();
}
}
);
});
}
</script>
Did you solved the problem? I had the same issue but I found this:
http://buildingwebapps.blogspot.ro/2011/11/jquerys-replacewith-and-using-it-to.html
I hope it helps you.