Update a shared view from different controllers - c#

I have a partial view which is being rendered in a shared layout called _Layout.cshtml.
_Layout.cshtml
<h1>#Html.Action("Home", "TestView");</h1>
Controller:
[ChildActionOnly]
public ActionResult TestView()
{
var model = new TestViewModel();
model.Title = "Default Title";
return PartialView("/Views/Shared/_TestView.cshtml", model);
}
_TestView.cshtml
#model TestMVC.Models.TestViewModel
#Model.Title
So far everything works fine, but I want to know if it is possible to update the model from a different action/controller.
Example in: localhost:8888/home/index, I want to display the default title which is "Default Title", but in certain actions/controller ex localhost:8888/home/contactus
I want to display a different title ex. "Contact us form title".
Is this possible?

just add an optional parameter:
[ChildActionOnly]
public ActionResult TestView(string title = "Default Title")
{
var model = new TestViewModel{ Title = title };
return PartialView("/Views/Shared/_TestView.cshtml", model);
}
then call it
<h1>#Html.Action("Home", "TestView", new { title = "Custom Title" })</h1>
or
<h1>#Html.Action("Home", "TestView")</h1> //use default title

Since your partial view is between <h1> tags, does this mean it will only function as a placeholder for text?
Either way, I get the feeling there are better solution than using partial pages.
You could simply use ViewBag to set a chosen field, e.g. ViewBag.CustomHeader = "Hello";.
Then you can remove the partial view and reference that field:
<h1>#ViewBag.CustomHeader</h1>
Keep in mind that you are then responsible for setting that value each time, or having the _Layout page provide a default value in case you didn't set it.
<h1>#(ViewBag.CustomHeader ?? "No title was set!")</h1>
A second option is possible by using Razor's sections to set the header. This would allow even HTML to be entered if you so choose.
Change your <h1> (including the tags) to:
#RenderSection("CustomHeader", required : false);
//you can set required to true if you need it.
Then, on any View you render, you can add a section by that name, and it will be added on the _Layout page instead of the contained View.
#section CustomHeader {
<h1>Hello, again! I'm another page!</h1>
<!-- You can add anything you want here -->
}
More info on sections can be found here.

Related

Assigning a value to the Controller depending on a link being click

I have a website with two forms one for inHole and the other Surface. The forms are identical but I would like to know where did the user clicked so I can assign a value to my SureyLocationID in the controller so I can refer to it later in my database if I need to without creating 2 views. Is there a way of doing so?
You can use Query string to pass a parameter with your link like :
http://example.com/over/there?sureyLocationID=inHole
or
http://example.com/over/there?sureyLocationID=Surface
So you just have to check the URL and retrieve the information you pass through it
In your MVC view have a button or anchor tag like this:
<a href='#Url.Action("YOUR_ACTION_NAME", "YOUR_CONTROLLER_NAME", new { comingFromInHole = true } )'>NAME_FOR_THIS_ELEMENT</a>
or
<input type="button"
onclick="location.href='#Url.Action("YOUR_ACTION_NAME", "YOUR_CONTROLLER_NAME", new { comingFromInHole = true} )'"
value="NAME_FOR_THIS_ELEMENT"/>
And in you MVC Controller:
public IActionResult YOUR_ACTION_NAME(bool comingFromInHole)
{
if (comingFromInHole)
{
// logic related coming from hole
}
else
{
// Logic related to surface
}
}
If you don't want to use boolean true or false, then you could use enumeration (or your custom defined type..etc) and use that as well:
public enum Types {InHole, Surface };
Then controller action signature will be changed to take in Types enum
public IActionResult YOUR_ACTION_NAME(Types type)
and modify your button or anchor link to send enum type to controller as below:
<a href='#Url.Action("YOUR_ACTION_NAME", "YOUR_CONTROLLER_NAME", new { Types=HomeController.Types.InHole} )'>NAME_FOR_THIS_ELEMENT</a>

ASP.net MVC 5 loading HTML.Partial from controller instead of loading on cshtml page

new to MVC so here goes.
I am currently loading up HTML.Partial on my Index.cshtml page like so:
#Html.Partial("~/Views/Switchb/editPerson.cshtml")
However, I am in need of customizing that in the controller depending on the current users category number.
So as an example, if the user has a category of 3 then I would need to do this:
#Html.Partial("~/Views/Switchb/3.cshtml")
Is there any type of call in the "code behind" in the controller that I can use in order to do that? Or would I just need to place the code within the cshtml page and pass its category number via the controller over to the cshtml page?
You can render a partial view from a controller action. You can pass the view name as string.
public ActionResult Switchb(string categoryNumber) {
var viewModel = new MyViewModel { CategoryNubmer = categoryNumber };
// additional processing, backend calls, formatting ....
return PartialView(categoryNumber, viewModel);
}
To call this action from View:
#{
var routeValues = new RouteValueDictionary(new {
categoryNumber= "3",
});
Html.RenderAction("Switchb", "MyController", routeValues);
}
Determine the category in the controller (via url parameter, from a database, or whatever) and then set that value as a property on your view's Model. Then in your line of code you can do this
#Html.Partial("~/Views/Switchb/" + Model.Category + ".cshtml");

Redirecting from cshtml page

I want to redirect to a different view depending on the result of a dataset, but I keep getting returned to the page I am currently on, and can't work out why. I drop into the if statement the action gets called but once i return the view to the new page, it returns me back to the current page.
CSHTML page
#{
ViewBag.Title = "Search Results";
EnumerableRowCollection<DataRow> custs = ViewBag.Customers;
bool anyRows = custs.Any();
if(anyRows == false)
{
Html.Action("NoResults","Home");
}
// redirect to no search results view
}
Controller
public ActionResult NoResults()
{
return View("NoResults");
}
View I cant get too..
#{
ViewBag.Title = "NoResults";
}
<h2>NoResults</h2>
Change to this:
#{ Response.Redirect("~/HOME/NoResults");}
Would be safer to do this.
#{ Response.Redirect("~/Account/LogIn?returnUrl=Products");}
So the controller for that action runs as well, to populate any model the view needs.
Source
Redirect from a view to another view
Although as #Satpal mentioned, I do recommend you do the redirecting on your controller.
This clearly is a bad case of controller logic in a view. It would be better to do this in a controller and return the desired view.
[ChildActionOnly]
public ActionResult Results()
{
EnumerableRowCollection<DataRow> custs = ViewBag.Customers;
bool anyRows = custs.Any();
if(anyRows == false)
{
return View("NoResults");
}
else
{
return View("OtherView");
}
}
Modify NoResults.cshtml to a Partial.
And call this as a Partial view in the parent view
#Html.Partial("Results")
You might have to pass the Customer collection as a model to the Result action or in a ViewDataDictionary due to reasons explained here: Can't access ViewBag in a partial view in ASP.NET MVC3
The ChildActionOnly attribute will make sure you cannot go to this page by navigating and that this view must be rendered as a partial, thus by a parent view. cfr: Using ChildActionOnly in MVC
You can go to method of same controller..using this line , and if you want to pass some parameters to that action it can be done by writing inside ( new { } )..
Note:- you can add as many parameter as required.
#Html.ActionLink("MethodName", new { parameter = Model.parameter })

how to catch id in aspx page in MVC

I'm working on a MVC production project.
In my Production details view I have some buttons to get some more data from the database, but for this I need the id of the Product. I can see it exist but can I catch it?
Here's my controller that return data:
public ActionResult Details(long AProductionOrderId)
{
ProductionOrderList item = new ProductionOrderList();
item = ProductionOrderReg.GetProductionOrders(conn, AProductionOrderId);
ViewData["item"] = item;
return View();
}
Here's my details page when it load, I can see the id, but how to catch and use it in the buttons in the left to bring more date ?
You could use a hidden input on your view page to submit the ID.
your View:
<form method="post">
<button type="submit">Button Text</button>
<input type="hidden" name="AProductionOrderId" value="#ViewData['item']">
</form>
i wrote this im my controller
ViewData["id"] = AProductionOrderId;
and catched it in my view
long id = Convert.ToInt64( ViewData["id"]);
If you controller is:
public ActionResult Details(long AProductionOrderId)
{
var item = ProductionOrderReg.GetProductionOrders(conn, AProductionOrderId);
ViewBag.ProductionOrderId = AProductionOrderId;
return View(item);
}
then your AProductionOrderId will be in the ViewBag although I don't see the reason why you need it since whatever the type of item is (single object instance or list of objects) it contains your ID as a property because you're fetching the item by this ID. Anyway in your model you then need to declare your model like this:
#model YourModelNamespace.ProductionOrderList
and now you can access any property of your model in your view. But if you really want you can access it via ViewBag like this:
#{
long AProductionOrderId = Viewbag.AProductionOrderId;
}

ASP.NET MVC Standard Link/Href As Save Button And Model IS NUll

Okay so, i am totally new to MVC and I'm trying to wrap my head around a few of the concepts. I've created a small application...
This application has a view for creating a new Individual record. The view is bound to a model ViewPage... And I have a associated IndividualController which has a New method...
The New method of the IndividualController looks like this...
public ActionResult New()
{
var i = new Individual();
this.Title = "Create new individual...";
i.Id = Guid.NewGuid();
this.ViewData.Model = new Individual();
return View();
}
Now, the above all seems to be working. When the view loads I am able to retrieve the data from the Individual object. The issue comes into play when I try and save the data back through the controller...
In my IndividualController I also have a Save method which accepts an incoming parameter of type Individual. The method looks like...
public ActionResult Save(IndividualService.Individual Individual)
{
return RedirectToAction("New");
}
Now, on my view I wanted to use a standard html link/href to be used as the "Save" button so I defined an ActionLink like so...
<%=Html.ActionLink("Save", "Save") %>
Also, defined in my view I have created a single textbox to hold the first name as a test like so...
<% using (Html.BeginForm()) { %>
<%=Html.TextBox("FirstName", ViewData.Model.FirstName)%>
<% } %>
So, if I put a break point in the Save method and click the "Save" link in my view the break point is hit within my controller. The issue is that the input parameter of the Save method is null; even if I type a value into the first name textbox...
Obviously I am doing something completely wrong. Can someone set me straight...
Thanks in advance...
Your New controller method doesn't need to create an individual, you probably just want it to set the title and return the view, although you may need to do some authorization processing. Here's an example from one of my projects:
[AcceptVerbs( HttpVerbs.Get )]
[Authorization( Roles = "SuperUser, EditEvent, EditMasterEvent")]
public ActionResult New()
{
ViewData["Title"] = "New Event";
if (this.IsMasterEditAllowed())
{
ViewData["ShowNewMaster"] = "true";
}
return View();
}
Your Save action should take the inputs from the form and create a new model instance and persist it. My example is a little more complex than what I'd like to post here so I'll try and simplify it. Note that I'm using a FormCollection rather than using model binding, but you should be able to get that to work, too.
[AcceptVerbs( HttpVerbs.Post )]
[Authorization( Roles = "SuperUser, EditEvent, EditMasterEvent")]
public ActionResult Save( FormCollection form )
{
using (DataContext context = ...)
{
Event evt = new Event();
if (!TryUpdateModel( evt, new [] { "EventName", "CategoryID", ... }))
{
this.ModelState.AddModelError( "Could not update model..." );
return View("New"); // back to display errors...
}
context.InsertOnSubmit( evt );
context.SubmitChanges();
return RedirectToAction( "Show", "Event", new { id = evt.EventID } );
}
}
If I don't create a new Indvidual object in the New method then when my view tries to bind the textbox to the associated model I get a NullReferenceException on the below line in my view...
`<%=Html.TextBox("FirstName", ViewData.Model.FirstName)%>`
With regards to the Save method. From what I understand since my view is strongly typed shouldn't I be able to have a method signature like...
`public ActionResult New(IndividualService.Individual ind)
{
return View();
}`
I thought that was the purpose behind model binding..?
I would strongly recommend that you take a step back from what you are doing and run through some of the Tutorials/Videos here http://www.asp.net/learn/
If you have a strongly typed View it means that when the Controller picks that view to generate the output the view has better access to the Model.
However the View is not responsible for what comes back from the client subsequently such as when a form is posted or a URL is otherwise navigated to.
ASP.NET-MVC uses information in the URL to determine which Controller to hand the request off to. After that it's the controller's responsibility to resolve the various other elements in the request into instance(s) of Model classes.
The relationship between the incoming request and the controller is clouded by the significant assistance the ASP.NET-MVC routing gives the controller. For example a route can be defined to supply parameters to the controller method and thats all the controller needs and hence you don't see any code in the method relating to the http request. However it should be understood that the contoller method is simply processing a http request.
I hope you can see from the above that it would be too early in a requests life-cycle for an instance of a class from the model to passed to a public method on a controller. Its up to the controller to determine which model classes if any need instancing.

Categories

Resources