T4MVC and Ajax method with parameter - asp.net-mvc

I am trying to apply T4MVC to my project. Say, I have an ajax search box, it calls Home/SearchQuery action which takes in a string q as parameter. How do I write that line in T4MVC?
From Ajax.BeginForm("SearchQuery", "Home", ....
To Ajax.BeginForm(MVC.Home.SearchQuery(???)...
.cshtml file
#using (Ajax.BeginForm("SearchQuery", "Home", /* <-----Convert to T4MVC Here */
new AjaxOptions {
LoadingElementId = "loadingGif",
OnSuccess = "parseResults",
OnFailure = "searchFailed"
})) {
<input type="text" name="q" />
<input type="submit" value="Search" />
<img id="loadingGif" style="display:none" src="#Url.Content("~/content/images/loading.gif")" />
}
<div id="searchResults" style="display: table"></div>

Your q is submitted from the input in form, so you could just write
#using (Ajax.BeginForm(MVC.Home.SearchQuery(),
new AjaxOptions {
LoadingElementId = "loadingGif",
OnSuccess = "parseResults",
OnFailure = "searchFailed"
})) {
<input type="text" name="q" />
<input type="submit" value="Search" />
<img id="loadingGif" style="display:none" src="#Url.Content("~/content/images/loading.gif")" />
}

Another possible answer: regenerate the template
I know it's a bit stupid, but I got here just because I forgot to regenerate the classes with the template (the new method with parameters is accessible before you regenerate the templates). Maybe someone will find this usefull.

Related

Correct way to handle multilple buttons on Begin Form

Would like to ask whether this way is correct or not to call two actions in a begin form
This works fine for me,would like to know whether this is the correct way or not.
I have added formaction="/Controller/Action" in button.
View
#using (Html.BeginForm("FileUpload", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<input type="submit" value="Update" id="btnSubmit" />
<input type="submit" value="Reset" formaction="/Home/Reset" id="btnReset"/>
}

MVC ASP.NET Map routing is not working with form GET request

In View-
#using (Html.BeginForm("PageName","ControllerName", FormMethod.Get))
{
<input type="hidden" name="categoryName" value="Insurance" />
<input type="hidden" id="cityName6" value="Irvine" name="cityName" />
<input type="hidden" name="page" value="1" />
<input type="submit" class="btn btn-default" value="Insurance" />
}
In RouteConfig-
routes.MapRoute(
"SomethingRouteName",
"{categoryName}/{cityName}/{page}",
new { controller = "ControllerName", action = "PageName" }
);
I want url to appear like this - Insurance/Irvine/1
But its coming like this- ControllerName/PageName?categoryName=Insurance&cityName=Irvine&page=1
This works fine when I use hyperlink instead of form get method.
#Html.ActionLink("Insurance", "PageName", "ControllerName", new{ categoryName = "Insurance", cityName = "Irvine", page = 1})
//URL shown: Insurance/Irvine/1 as expected.
But I have to use form GET method so this hyperlink way is useless.
Please help
You're not passing any route values to Html.BeginForm, so your rendered form element looks like this:
<form action="/ControllerName/PageName" method="get">
</form>
So when you click submit, it simply appends the values of the form as a query string.
To fix this:
#using (Html.BeginForm("PageName", "Home", new {categoryName = "Insurance", cityName = "Irvine", page = "1"}, FormMethod.Get))
{
<input type="submit" class="btn btn-default" value="Insurance" />
}

Submitting a form to ASP.NET MVC from Knockout does not bring in all the values

Here is what I have in my view in ASP.NET MVC 5
#model Entities.Coupon
#using (Html.BeginForm("coupon", "marketing", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div class="scsm-18 scmd-16 sclg-14">
<div class="form-group">
<label>Codes</label>
#Html.TextBoxFor(p => p.Code, new { #class = "form-control", #data_bind = "value: Code", #autofocus = true, #maxlength = "50" })
</div>
<input type="radio" name="IsPerCentOrDollar" value="1" data-bind="checked: IsPerCentOrDollar" />
<span>PercentageAmount</span>
<input type="radio" name="IsPerCentOrDollar" value="2" data-bind="checked: IsPerCentOrDollar" />
<span>DollarAmount</span>
<input type="radio" name="IsPerCentOrDollar" value="3" data-bind="checked: IsPerCentOrDollar" />
<span>FreeShipping</span>
</div>
<div class="panel-footer text-right">
<input type="submit" name="commandType" id="btnSave" class="btn btn-primary" data-bind="click:submit" value="Save" />
</div>
}
In the script:
$(document).ready(function () {
var viewModel = new CouponViewModel(couponModel);
ko.applyBindings(viewModel);
function CouponViewModel(data) {
self.Code = ko.observable(data.Code);
self.IsPerCentOrDollar = ko.observable("1");
self.DiscountLevel = ko.computed(function () {
return self.IsPerCentOrDollar();
});
};
}
Code in MVC:
[HttpPost, ActionName("coupon")]
public ActionResult coupon(Coupon coupon)
{
try
{
// some logic not yet in
}
catch (Exception ex)
{
}
return View();
}
That's all I have in there now.
In Developer tools inside the browser I can see values for self.DiscountLevel change on the selection of radio buttons.
On Submit, at MVC front the value of Code comes in but the values for DiscountLevel are not.
Any help is greatly appreciated.
Regards.
Let me expand on #StephenMuecke's comment (which has the gist of it I think).
ASP.NET MVC's default model binding will fill the argument (Coupon) with values found in the request. Only form elements are sent along with the request. You seem to expect that DiscountLevel is sent along, but it's just a JavaScript function that exists in the user's browser.
Adding something like this may solve your immediate problem:
<input type="hidden" name="DiscountLevel" data-bind="value: DiscountLevel" />
To note a related issue though: the property you have trouble with is a computed observable. However, you probably do not want to send it along as it depends entirely on IsPerCentOrDollar. Just have your server side Coupon class derive the discount level from that property too. That would also prevent users from hacking the hidden input and sending in a malicious value.

#Html.Beginform() not rendering properly IE7-8

I have a HTML form which is in a partial that is loaded via jquery.load(). My partial looks something like this:
#Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data", id = "addComicForm"}){
<div class="add-comic-submit">
<input type="submit" value="haha" name="haha" />
</div>
}
On IE7-8 It's not rendered properly and does not create a form attribute, however, if I manually insert the form code such as
<form action="/ManageComics/ComicAdder" enctype="multipart/form-data" id="addComicForm" method="post" novalidate="novalidate"> </form>
It works properly.
Because you are doing it wrong. It should be like this:
#using (Html.BeginForm("ComicAdder", "ManageComics", FormMethod.Post, new { enctype = "multipart/form-data", id = "addComicForm" }))
{
<div class="add-comic-submit">
<input type="submit" value="haha" name="haha" />
</div>
}
another way should like this:
#{
Html.BeginForm("your actionName", "your controllerName", FormMethod.Post);
}
<div class="add-comic-submit">
<input type="submit" value="haha" name="haha" />
</div>
#{
Html.EndForm();
}

Multiple forms in ASP.NET MVC

Context
Let`s say i have:
In layout Site.Master:
<div class="leftColumn">
<asp:ContentPlaceHolder ID="MainContent" runat="server" />
</div>
<div class="rightColumn">
<% Html.RenderPartial("_Login"); %>
<asp:ContentPlaceHolder ID="SideContent" runat="server" />
</div>
Login partialView looks like:
<form action="/myApp/Account/Login" method="post">
<input name="name" />Name<br />
<input name="password" type="password" />Password<br />
<button>Login</button>
</form>
Is it possible to update only login widget form, not the entire content page?
If you are referring to a http post, only a post initiated (it can also be initiated by javascript) by a submit button from within the form will be posted to the server.
If your forms are nested then this won't work. The outer form will always post to the server.
In the sample HTML below, clicking on the submit button on the first form will not send the values from the second form to the server. Likewise, clicking the second submit button won't post the values from the first form.
<html>
...
<body>
<div>
<form action="/Login/Login" method="post">
<input type="text" name="username" value="" />
<input type="text" name="passowrd" value="" />
<input type="submit" name="login" value="Login" />
</form>
<form action="/Login/AdminLogin" method="post">
<input type="text" name="username" value="" />
<input type="text" name="passowrd" value="" />
<input type="submit" name="login" value="Login Admin" />
</form>
</div>
</body>
</html>
If you only wish to update/change one of the form section, then no this can not be done without using javascript and performing a javascript post(aka Ajax).
If you build a controller method that accepts a FormCollection and your view has two forms defined, the formcollection returned will either be populated with values from form A or form B. You can inspect the formCollection and branch your logic based on the value therein. If you want the be very explicit you could have the same hidden variable occur in both forms with a value that would help your make your choice.
That's one approach. there are a few ways to deal with this I'm sure.
If you have two simple forms, you can use this aproach:
You create two different partial views.
#model CustomerInfoModel
#using (Ajax.BeginForm("CustomerInfo", "Customer", new AjaxOptions { HttpMethod = "Post", OnBegin = "InfoLoading", OnComplete = "InfoCompleted" }, new { id = "info", #class = "form-horizontal" }))
{
<input type="text" class="form-control" name="Name" id="Name" value="#Model.Name" />
<input type="email" class="form-control" name="Email" id="Email" value="#Model.Email" />
<button type="submit" id="save-info" class="btn-medium red">Save</button>
}
and
#model CustomerPasswordChangeModel
#using (Ajax.BeginForm("CustomerPasswordChange", "Customer", new AjaxOptions { HttpMethod = "Post", OnBegin = "InfoLoading", OnComplete = "InfoCompleted" }, new { id = "change", #class = "form-horizontal" }))
{
<input type="password" class="form-control" name="OldPassword" id="OldPassword" value="" />
<input type="password" class="form-control" name="NewPassword" id="NewPassword" value="" />
<button type="submit" id="save-change" class="btn-medium red" autocomplete="off">Save</button>
}
In your parent view,
#Html.Partial("CustomerInfo", Model.CustomerInfo)
and
#Html.Partial("CustomerPasswordChange", Model.CustomerPasswordChange)
In Controller:
[HttpPost]
public ActionResult CustomerInfo([Bind(Include = "Name,Email")] CustomerInfoModel model)
{
if (ModelState.IsValid)
return new Json(new { success=true, message="Updated.", errors=null);
// do you logic
return new Json(new { success=false, message="", errors=getHtmlContent(ModelState.Values.SelectMany(v => v.Errors).ToList(), "ModelError"));
}
[HttpPost]
public ActionResult CustomerPasswordChange([Bind(Include = "OldPassword,NewPassword")] CustomerPasswordChangeModel model)
{
if (ModelState.IsValid)
return new Json(new { success=true, message="Updated.", errors=null);
// do you logic
return new Json(new { success=false, message="", errors=getHtmlContent(ModelState.Values.SelectMany(v => v.Errors).ToList(), "ModelError"));
}
This will do what you want to do.
Note: getHtmlContent method is just generating an error message to be displayed on page. Nothing so special. I may share it if required.
Your question is not very clear.
But as far as I could understand, the answer is most likely yes. You can update anything you want depending on the user input.
if(pass != true)
{
ViewData["Message'] = "Hey your login failed!"; Return View("Login")
}
On ViewPage
<form action="/tralala/Account/Login" method="post">
<input name="name" />Name<br />
<input name="password" type="password" />Password<br />
<button>Login</button>
<div style="color: red"><%=ViewData["Message"] %><div>
</form>

Resources