I have two Asp.Net MVC Websites. The first one is inside the root domain domain.com, and the second one is a subdomain sub.domain.com.
Everything works fine inside the root domain, but I'm having trouble submitting a form to a controller on the subdomain. Whatever I try to send seems never to get to the controller.
It may seem strange but this problem does not happen when I try to start the application locally in debug mode. (locally is not a subdomain, just plain localhost).
Just for testing purposes I've build a simple model:
public class TestModel
{
public string test_text { get; set; }
}
And this is the CSHTML partial view:
#using (Html.BeginForm("TryModel", "Home", new { }, FormMethod.Post, new { }))
{
<input type="text" name="test_text" />
<button type="submit">Test</button>
}
Even with this simple configuration, on my local copy I've no problem, but as soon as I start the application on the remote machine, the posted data is always empty.
What do you think could be the problem?
EDIT
This is the controller methods
[HttpGet]
public ActionResult TryModel()
{
return View();
}
[HttpPost]
public ActionResult TryModel(TestModel model)
{
// code removed
return View(model);
}
And yes, the action is called correctly. Even the Request.Form is empty.
Html.BeginForm takes only 4 Parameter,
Parameters: string actionName, string controllerName, FormMethod method, object htmlAttributes
you should change the your parameter
from:
#using (Html.BeginForm("TryModel", "Home", new { }, FormMethod.Post, new { }))
to:
#using (Html.BeginForm("TryModel", "Home", FormMethod.Post, new { }))
I hope it will helps.
Related
I have an action like this
public ActionResult Overview(TimeAxisVM TimeAxis = null)
{
return View(new OverviewVM());
}
View model like this
public class TimeAxisVM
{
// omitted ctor
[DataType(DataType.DateTime)]
public DateTime? From { get; set; }
[DataType(DataType.DateTime)]
public DateTime? To { get; set; }
}
An editor template for the view model
#model TimeAxisVM
#using (Html.BeginForm("Overview", "Controller", FormMethod.Get))
{
#Html.EditorFor(model => model.From)
#Html.EditorFor(model => model.To)
<button type="submit">Submit</button>
}
And a view for the Overview action like this
#model OverviewVM
#Html.EditorFor(model => model.TimeAxis)
When I execute the GET request this is the query string is TimeAxis.From=22.+02.+2014&TimeAxis.To=25.+02.+2014 but once in the action TimeAxis.From and TimeAxis.To are both null.
If I change the form method to POST it immediately works as expected. From design point of view this should/has to be a GET request.
Any ideas how to make the model binding work for GET?
UPDATE:
Changing the action to
public ActionResult Overview(DateTime? From = null, DateTime? To = null)
and sending the request in this form: .../Overview/?From=22.+02.+2014&To=25.+02.+2014 works as well.
But I'd like to keep it encapsulated in the class and dont need to change the input field name - EditorFor generates them as TimeAxis.From and TimeAxis.To. I might add other properties to the ViewModel/form.
I found the answer. HTTP GET requests are culture invariant, whereas HTTP POST requests respect current culture in ASP.NET MVC.
http://weblogs.asp.net/melvynharbour/archive/2008/11/21/mvc-modelbinder-and-localization.aspx
If you want to bring the Model again into the view, you need to pass the ModelView back to the View like
return View(TimeAxis);
then, I think you do not have a controller called Controller do you? You might have a HomeController or something else, no?
in that case, please amend you form to
#using (Html.BeginForm("Overview", "Home", FormMethod.Get))
if for example you're Overview action is in the Home controller
all in all, your controller and view should be:
public ActionResult Overview(TimeAxisVM TimeAxis)
{
return View(TimeAxis);
}
and
#using (Html.BeginForm("Overview", "Home", FormMethod.Get))
{
#Html.EditorFor(Model => Model.From)
#Html.EditorFor(Model => Model.To)
<button type="submit">Submit</button>
}
here's the screencast of the code above: http://screencast.com/t/7G6ofEq0vZEo
Full source: http://ge.tt/1Uh80pK1/v/0?c
I'm new to ASP.NET MVC 4.
I'm able to create a folder with a hardcoded name using Directory.CreateDirectory(#"C:/") in my controller, but what I need to do is have the user type the desired folder name into a textbox, and pass that information to the CreateFolder method in the Controller.
Here's the method:
public ActionResult CreateFolder(String newFolderName)
{
Directory.CreateDirectory(#"C:\..." + newFolderName);
return View();
}
In my view I need a textbox for the user to define the desired folder name, and a button that creates the folder with the selected name.
How should I handle this?
I've tried some suggestions from the web, but can't seem to get it going.
View:
#using Folder
#using ( #Html.BeginForm( "CreateFolder", "ControllerName", FormMethod.Post) )
{
#Html.TextBoxFor(x=>x.FolderName)
<input type="submit" id="btnCreateFolder" value="Create Folder" />
}
Model:
public class Folder
{
// other properties
string FolderName {get;set;}
}
Controller:
[HttpPost]
public ActionResult CreateFolder(Folder model)
{
Directory.CreateDirectory(#"C:\..." + model.FolderName);
return View();
}
I have a controller:
public class LanguageController : Controller
{
[HttpGet]
public ActionResult Index()
{
// populate viewModel from database
return PartialView(viewModel)
}
[HttpPost]
public ActionResult Index(string language)
{
LanguageCookie.Write(Response, language);
return RedirectToAction(ACTION, CONTROLLER, new {culture = language});
}
}
and its partial view:
#model MyModel
#using (Html.BeginForm("Index", "Language"))
{
#Html.DropDownList(
Model.SelectedLanguageShortName,
Model.AllLanguages
)
<input type="submit" value="Select" />
}
which I render in _Layout.cshtml:
<div>
#Html.Action("Index", "Language")
</div>
Please let me know how can I get ACTION/CONTROLLER names of main (not partial) controller, from my LanguageController was called. I need this information on the postback where I set cookie and want to redirect user on the same page but with prefered language.
I have found this example:
var rd = ControllerContext.ParentActionViewContext.RouteData;
var currentAction = rd.GetRequiredString("action");
var currentController = rd.GetRequiredString("controller");
But ControllerContext.ParentActionViewContext is null in the postback. I am able to get what I need in the view but it is ugly:
#Html.Hidden("Controller", HttpContext.Current.Request.RequestContext.RouteData.Values["controller"].ToString());
#Html.Hidden("Action", HttpContext.Current.Request.RequestContext.RouteData.Values["action"].ToString());
How to get the same information in the controller scope?
When Index(string language) is processed ParentActionViewContext is null because this is another request to server and it doesn't know anything about previous request that invoked child action.
Instead of storing control and action in hidden field you can store the whole address and invoke Redirect:
#model MyModel
#using (Html.BeginForm("Index", "Language", new { redirectUrl = Request.Url }))
{
#Html.DropDownList(
Model.SelectedLanguageShortName,
Model.AllLanguages
)
<input type="submit" value="Select" />
}
and then
[HttpPost]
public ActionResult Index(string language, string redirectTo)
{
LanguageCookie.Write(Response, language);
return Redirect(redirectTo);
}
Another way is to save CONTROLER and ACTION in TempData, but in this way you can have problem if somebody open multiple pages of your site.
Third solution is to invoke that method with Ajax and when response arrive reload the page with javascript.
i have a action method for login with get method:
public virtual ActionResult LogIn()
{
return View();
}
and an action method for Post method which post in Ajax call with Ajax.BeginForm(),like:
[HttpPost]
[AjaxOnly]
[ValidateAntiForgeryToken]
public virtual ActionResult LogIn(LogInViewModel loginInfo, string returnUrl)
{
...
}
But returnUrl always is null!!!
i use MVC 4.
what is cause of this problem?
You have to send the returnUrl back to the server. For example your login form should take returnUrl as a parameter:
#using (Html.BeginForm(new { ReturnUrl = ViewBag.ReturnUrl })) {
....
<input type="submit" value="Log in" />
}
which was previously saved at the server side in your login action, invoked as a result of usage AuthorizeAttribute with ReturnUrl passed in the query string:
public ActionResult Login(string returnUrl)
{
ViewBag.ReturnUrl = returnUrl;
return View();
}
Not sure what your view looks like, but if you have something like:
#using (Html.BeginForm())
{
}
...then returnUrl should have a populated value, that's if it came from another url.
In my scenario it was always null, and I am assuming it was probably the same way that you did it. I had it like this:
#using (Html.BeginForm("LogOn", "Account", FormMethod.Post, new { role = "form" }))
{
}
All that I did was change it to look like this:
#using (Html.BeginForm("LogOn", "Account", new { returnUrl = Request.QueryString["ReturnUrl"] }, FormMethod.Post, new { role = "form" }))
{
}
returnUrl now has a value that I can work with.
in continue for Completion good answer of #Jaroslaw Waliszko,cause of this problem is:
because we use a ajax request for submit form,unobtrusive ajax use
$("form").serialize();
for this form and at this case(use ajax) ReturnUrl(and any other parameter) not send to server and only form input element send to server,So MVC Auto ModelBinding not bind ReturnUrl and we must use #Jaroslaw Waliszko solution at this state.
serialize
Encode a set of form elements as a string for submission.
I have an MVC app and I've run into a problem with modern multitab browsers.
I have a screen that creates a model and stores it in this.TempData["MyViewModel"]
I then open the same screen in a 2nd tab and as it calls the same controller methods this.TempData["MyViewModel"] is once again set.
If I then go back to Tab 1 and refresh the page, I am presented with the data I entered in Tab 2.
Is there a way to store data in TempData uniquely per browser tab ?
I have toyed with the idea of creating a unique TempData key and persist it between requests using either the querystring or a hidden field but this seems messy.
Any ideas / advice would be most welcome. :o)
What I have so far is a concept of a 'ProcessID'.
In my first partial view I have a form with a hidden field which is loosely bound to my Model.ProcessID. When the form is posted this hidden field ProcessID is used as the TempData key...
Example:
public sealed class MyViewModel
{
public MyViewModel()
{
this.ProcessID = Guid.NewGuid().ToString();
}
public string ProcessId { get; set; }
// other fields
}
Partial View 1:
#model Models.MyViewModel
#using (Ajax.BeginForm("PartialView1", "Home", new { }, new AjaxOptions() { UpdateTargetId = "myDivToUpdate" }, new { }))
{
#Html.HiddenFor(m => m.ProcessId);
// other fields...
<input type="submit" value="next" />
}
public ActionResult PartialView1(FormCollection form)
{
return this.PartialView("PartialView1", new Models.MyViewModel());
}
[HttpPost]
public ActionResult PartialView1(FormCollection form)
{
Models.MyViewModel vm = new Models.MyViewModel();
this.UpdateModel(vm, form);
this.TempData[vm.ProcessId] = vm;
return this.PartialView("PartialView2", vm);
}
In my 2nd partial view form I once again have a hidden field loosely bound to the same Model.ProcessID. When this form is posted I can use the Model.ProcessID to retrieve my viewmodel from TempData and update it:
Partial View 2:
#model Models.MyViewModel
#using (Ajax.BeginForm("PartialView2", "Home", new { }, new AjaxOptions() { UpdateTargetId = "myDivToUpdate" }, new { }))
{
#Html.HiddenFor(m => m.ProcessId);
// other fields (different to partial view 1)...
<input type="submit" value="finish" />
}
[HttpPost]
public ActionResult PartialView2(FormCollection form, Models.MyViewModel vm)
{
vm = (this.TempData[vm.ProcessId] as Models.MyViewModel);
this.UpdateModel(vm, form);
return this.Json(new { result = true, message = "success" }, JsonRequestBehavior.AllowGet);
}
By default I believe MVC uses session state to store TempData using the SessionStateTempDataProvider and therefore each TempData will be stored in the same place for that session. Using session the only around this that I can see is to use some identifier as you suggested.
However you can implement the ITempDataProvider interface to use your own provider that could then store this data in some other form of storage (such as cookies or sql).