I have called a view from another with Html.Action method. I want to call the same action with a parameter Inside the child view, when user click the action link.
When I write this code I get this error message:
Html.ActionLink("link", "Configure", new { id = 2 })
The action 'Configure' is accessible only by a child request.
How can i handle this issue?
Edit: I'll try to reexplain the issue:
my parent view is ConfigureMethod.cshtml. I call child child view like that:
#Html.Action("Configure", "Payment");
It goes to this controller and returns actionresult(not partialview) inside ConfigureMethod view:
[ChildActionOnly]
public ActionResult Configure()
{
}
inside configure view i make an action link like that:
Html.ActionLink("link", "Configure", new { id = x.Id })
It should goes to this controller:
[ChildActionOnly]
public ActionResult Configure(int Id)
{
}
However when childonly attribute is written it gives error. When I remove this attribute it works but results comes directly, not inside ConfigureMethod view.
thanks.
There are two things I would like to point out,
Child actions are only meant to be rendered as PartialView. So decorating with [ChildActionOnly] attribute means, this is the action must return PartialViewResult.
When we are calling ActionLink(), it will generate a link to a View not Partial View. Even if you will not decorate with [ChildActionOnly], then a link to a partial view makes no sense.
So, first decide if you want a View or Partial View and then design accordingly.
Related
I have a view with two forms each containing their own
#Html.ValidationSummary()
When the page is loaded, a querystring parameter is checked and if it exists I call:
ModelState.AddModelError("", "Querystring error");
However, this results in the error message appearing in both #Html.ValidationSummary() even if I specify a property in the form model.
I have a work around which is to have a seperate error message property in the model for the form and populate that and then display it if it exists in a label, but wondered if it is possible to specify one individual #Html.ValidationSummary() within a form to allow me to use ModelState.AddModelError?
Following the helpful information I was given by #GSerg, I thought I'd share my resolution.
So instead of having two forms within the same view, I split each form into two separate partial views and called each from within the main view...
#Html.Action("_RequestPartial")
#Html.Action("_LoginPartial")
Each partial view would contain the model to pass to it and a Html.BeginForm with a Html.ValidationSummary() inside.
Then within the Controller, set up the code to return the view as normal (in this case for the Index view)...
[HttpGet]
public ActionResult Index()
{
return View();
}
Then for the partial views, set up a PartialViewResult for each partial view annotated with ChildActionOnly...
[ChildActionOnly]
public PartialViewResult _RequestPartial()
{
... code that populates model you want to pass ...
return PartialView(model);
}
[ChildActionOnly]
public PartialViewResult _LoginPartial()
{
... code that populates model you want to pass ...
return PartialView(model);
}
Hope this helps someone.
To show the specific validation message, please see the snippet code below.
Controller :
[HttpGet]
public ActionResult Index()
{
ModelState.AddModelError("Error1", "Querystring error");
return View(new SampleViewModel());
}
View :
#Html.ValidationMessage("Error1")
Just tried to create a fiddle to get a complete picture. https://dotnetfiddle.net/GoMMhy
I'm new to MVC, so please go easy on me. I was handed a project that was started in MVC and have been told to add to it. I was fine until I got to a section that needed data from two different models. Now I'm stuck and my boss wants this done yesterday. Please help if you can.
I have a view with two partial views and a submit button. Each of the partial views use a different model. The views display information on the screen which the user can change. The submit button is then clicked. In the controller, I would like to access the data from both models (the values that the user entered on the screen). Right now, I can't even get the submit button to call the controller. That is the part I need immediate help with, but I will eventually need to know how to access both model's data from the controller.
Here's the basic idea of what I want to do:
This is my view: CreateContract.cshtml
<div class="container-fluid">
#using (Html.BeginForm("CreateContract", "CreateContract", FormMethod.Post, new { #class = "form-horizontal " }))
{
<div id="PartialDiv">
#{
Html.RenderPartial("ApplicationPartialView", new CarmelFinancialWeb.Models.ModelApplication());
Html.RenderPartial("ContractPartialView");
}
</div>
<input id="btnCreateContract" type="submit" class="btn btn-primary" value="Save" name="CreateContract" />
}
</div>
This is part of the controller CreateContractController.cs. This method is hit when the view opens and is working correctly.
[AuthorizeAdmin]
public ActionResult CreateContract(string ID)
{
ModelContract obj_Contract = new ModelContract();
obj_Contract.BuyerName = "MOCS";
return View(#"~/Views/CreateContract/CreateContract.cshtml", obj_Contract);
}
This is part of the controller CreateContractController.cs. This method is not being hit when the submit button is clicked. I've tried including the string ID variable from the other method and both ModelContract and ModelApplication (and various combinations thereof), but I cannot get this method to be called.
[AuthorizeAdmin]
[HttpPost]
public ActionResult CreateContract()
{
ModelApplication obj_App = new ModelApplication();
return View(#"~/Views/CreateContract/CreateContract.cshtml", obj_App);
}
These are the methods in the controller for the partial views. These aren't getting called either.
public PartialViewResult ApplicationPartialView(string ID)
{
ModelApplication obj_App = new ModelApplication();
if (ID != null && ID != "0" && ID != null && ID != "")
{
obj_App = objBllApplication.GetApplicationByID(int.Parse(ID));
}
return PartialView("CreateContractApplicationPartialView");
}
public PartialViewResult ContractContractPartialView()
{
ModelContract obj_Contract = new ModelContract();
obj_Contract.DealerID = "MOCS";
return PartialView("CreateContractContractPartialView");
}
There's a lot going on under the hood here which is beneficial for you to know, especially since you're new to this. First, a view can only have one model. The high-level reason is that it's actually rendered via a generic class that the chosen model fills in as it's type. You can somewhat cheat, as you are here, by using partial views, but you still have to get a model instance into those. It's seems you're trying to do that by creating actions in your controller to represent those partials, but these are effectively useless. They are never being called. Html.Partial or Html.RenderPartial will just render the specified view, either with the same model as the calling view, by default, or the object passed in to those methods as the model (second parameter). It does not go back to the controller.
In MVC, there is something called "child actions" which work as you seem to want partials to here. By using Html.Action or Html.RenderAction instead, you can call this actions on your controller that return partial views. Two things there, though:
If you're going to return a partial view (instead of a full-fledged view), then you should decorate the action with [ChildActionOnly]. Otherwise, the actions are exposed to direct URL access from the browser, which would render the partial view alone, without any layout.
Child actions can only be used for GET-style requests. You can't POST to a child action.
It's actually best for things like this, to only use child actions to render separate areas of a form if those individual areas of the form will be posted to separate locations. Take for example a combo page where you have both a login or signup concept. You can use child actions to render each individual group of fields, but the login portion should POST to a login action and the signup portion should posted to a signup action. You wouldn't POST everything from both forms to the same action.
In your particular scenario, partial views are actually the way to go, but you just need to tweak the model of your main view to be a view model that contains both sub-models. For example:
public class MyAwesomeViewModel // name doesn't matter
{
public ModelApplication Application { get; set; }
public ModelContract Contract { get; set; }
}
Then, in your main view:
#model Namespace.To.MyAwesomeViewModel
...
#Html.Partial("ApplicationPartialView", Model.Application)
#Html.Partial("ContractPartialView", Model.Contract)
Finally, your POST action would take this view model as a parameter:
[HttpPost]
public ActionResult CreateContract(MyAwesomeViewModel model)
{
...
}
One of the View methods on the Controller class (in System.Web.Mvc) allows you pass a model to a different view. However, it does not update the url to the name of the new view because this method works more like Server.Tranfer than Response.Redirect. The point is that this behaviour can be confusing to anyone picking-up MVC. So, after the View method has been called, I would like the url path to be rewritten to reflect the name of the new view. I have tried the following, which does not work, on a class that implements the Controller class:
public ViewResult ViewAsRedirect(string viewName, object model)
{
var baseView = base.View(viewName, model);
ControllerContext.HttpContext.RewritePath(baseView.ViewName);
return baseView;
}
What's the correct code to implement what I have described?
EDIT
Any RedirectToAction method does not allow you to send you model to another action. There is a dirty workaround where you store it in TempData before you exit one action and retrieve it at the beginning of another action. I don't want to use this pattern. This is why I am using View(...) instead.
You simply cannot "update the URL" (i.e. redirect) and return content.
If you want the new URL to show the same content as you anticipated, then you'll need to (temporarily) store the results and include an identifier for the resource that you wish to display on the redirected URL.
There you can pull the resource in from the controller for the redirected URL again, and display it on the appropriate view.
So if you POST your object model to /Foo/Create, you can for example store model in a database, which yields an ID: 42. Then you can redirect to /Foo/View/42, and display it.
If you can explain what you are actually trying to do, a more concrete answer can be given.
RedirectToAction is very intuitive in my opinion... you should use one of the redirecting methods of MVC controller: Redirect(url), RedirectToAction(acion), RedirectToAction(acion, controller), and so on.
example
public class HomeController : Controller
{
[HttpGet]
public ActionResult Index()
{
return View();
}
public ActionResult Redirect()
{
return this.RedirectToAction("Index");
}
}
EDIT
If your action needs to collect tons of data to pass to the view, you could redirect very early, by detecting the condition of redirection, and loading all the data inside the other action, based on simple route data such as database IDs, or simple strigs or numbers.
== OR ==
You can render javascript code to change the URL in the client side, when the page loads: Modify the URL without reloading the page
This works only in very recent browsers (current date nov/2013).
how can i remove the child action in asp.net mvc3. I mean i am having partial views and main views. In the url bar when i entered the child page then it should not load.
for suppose my main page is
localhost:5820/Home/Index
Then when i enter
localhost:5820/Home/Index
then it should work and the child item is
localhost:5820/Home/About
Then when i enter
localhost:5820/Home/About
then it should not open. How can i do that in asp.net mvc. I have several pages like that i have displayed the pages in how can
i rectify this issue
Looks like you are looking for ChildActionOnly attribute:
[ChildActionOnly]
public ActionResult About()
{
return View();
}
It disables direct calls to localhost:5820/Home/About - only rendering as partial view will be available.
UPDATE according to what you need - mark all actions which should return partial views with ChildActionOnly attribute:
public ActionResult Index()
{
return View();
}
[ChildActionOnly]
public ActionResult About()
{
var model = ...
return PartialView("_About", model);
}
And in index view call those actions (from Home controller and other controllers) via:
#Html.Action("About", "Home")
The fact that your ABOUT page is a link inside your HOME page does not mean it is a child action, in fact, from the point of view of MVC they are in the same level, is YOU as a programmer that give the ilussion of hiereachies by providing an order of navigation.
Now, what you can do is:
simply remove the Action Methods from your controller, or
write a simple ignore route like:
routes.IgnoreRoute("YourRuleToIgnoreActions");
this rules should be at the beginning of your RegisterRoutes method in RegisterRoutes to avoid other rules to be triggered
To build up your ignore rules, here is a nice discussion on the topic: http://ardalis.com/IgnoreRoute-in-ASP.NET-Routing-is-Order-Dependent
UPDATE:
Probably too much thinking on this one, but in my opinion, the Models CAN have properties that modify the behaviour of the View, this is because from an architectural point of view, when you are already in the View, your concern is exclusively on the presentation layer, so I think it is perfectly valid to have something like:
public class MyReportsModel{
public bool displaySection1 { get; set;}
//other data
}
and in your views, you can change the presentation in the following way:
#{
if(#Model.displaySection1){
//display as normal
}
}
Of course, when you populate the model you should set that property in each controller according to your needs:
MyReporstModel thisView = new MyReportsModel();
thisView.displaySection1 = true;
// set all properties necessary to display
// if the controller knows that this partial view won't be displayed then
thisView.displaySection1 = false;
But that is no longer a technical issue but an architectural one.
hope it helps,
In ASP.NET MVC I have a controller that looks somehow like this:
public class MyController{
public ActionResult Index(){
return View(new MyModel());
}
[HttpPost]
public ActionResult Index(MyModel model){
//do something
return View("RegistrationConfirmation", new ConfirmModel());
}
[HttpPost]
public ActionResult RegistrationConfirmation(ConfirmModel model){
//do something else
return View();
}
}
User's workflow that I'd like to have is following
GET page index. Returns view Index. URL: ~/My
POST data from Index page - returns view RegistrationConfirmation and send the user to right page ~/My/RegistrationConfirmation.
User POSTs another data while on RegistrationConfirmation page so that RegistrationConfirmation gets called to process them.
Right now action method RegistrationConfirmation is never called because after returning RegistrationConfirmation view by Index action method URL stays ~/My so the second post is processed by Index(MyModel) action method not by RegistrationConfirmation(ConfirmModel) action method.
How can I change URL along with sending the View so that the controller action that corresponds to the view gets called on POST back ? Or is there any other way how to ensure that corresponding controller is called?
NOTE: I have really read more than 20 questions that seemed to be on topic before posting this one. I don't think perfect answer to any of them will give me solution. Please read properly before voting to close as duplicate.
try this one in the view RegistationConfirmation
you can easily add the action and the controller which should be targeted in the Html.BeginnForm command...
<% using(Html.BeginForm("RegistrationConfirmation", "MyController")){%>
//form elements
<%}%>
with this you exactly define which action and controller is going to be called