First, I use Asp.Net MVC 2 RC 2.
What I want to do is to list a comment view and below this view being able to add comment (with validations). For example, something like when you add comment in stackoverflow. Except that my page should work with or without javascript enabled.
So to solve that problem I use the new RenderAction and it partially solved my problem. I got my list view that calls my addcomment usercontrol with RenderAction.
The validations work. My problem occurs when I try to add a comment that it's valid. The page didn't refresh correctly. If I got in the database, my comment is added, but it's doesn't have been refresh in my list view and the add comment form isn't clear.
I think it's because of how the workflow is rendered.
Maybe if someone got a example or blog about this, it's can help me to get it right...
At the bottom of my Comment/List.aspx
<% Html.RenderAction("Create", "Comment"); %>
In Comment/Create.ascx
<% using (Html.BeginForm(
ViewContext.ParentActionViewContext.RouteData
.Values["action"].ToString(),
ViewContext.ParentActionViewContext.RouteData
.Values["controller"].ToString(),
FormMethod.Post, new { id = "createForm" })){ %>
You can force the parent View to refresh itself with a small hack involving ViewContext.ParentActionViewContext.
In your CommentController class:
public ActionResult Create(Comment comment)
{
...
if (isValid) // Comment entered in form is valid
{
ControllerContext.ParentActionViewContext.ViewData["SuccessfullCreate"] = true;
}
...
}
And in your Comment/List.aspx page (view) :
<% Html.RenderAction("Create", "Comment"); %>
<%
if (ViewContext.ViewData["SuccessfulCreate"] != null)
{
string action = ViewContext.RouteData.Values["action"].ToString();
string controller = ViewContext.RouteData.Values["controller"].ToString();
string url = "/" + controller + "/" + action;
Response.Redirect(url);
}
%>
So basically, what's happening is that the child action is "telling" the parent action to refresh itself by using the parent's ViewData.
It's kind of a hack, but it works fine for what's you're doing.
Related
I have a usercontrol named "LoginUserControl.ascx" which I have placed in a master page.
Header of "LoginUserControl.ascx"
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<MultiTechnologyWeb.Models.loginmodel>" %>
Then I used the below code to show the usercontrol in the masterpage.
<% Html.RenderPartial("LoginUserControl"); %>
On first run the page "index" is loaded.
Notice the header of the "index" page, no model is specified. Thus page load successfully
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/MT.Master" Inherits="System.Web.Mvc.ViewPage<dynamic>" %>
Now I click on the link to open register.aspx. I got the below error
The model item passed into the dictionary is of type 'MultiTechnologyWeb.Models.registermodel', but this dictionary requires a model item of type 'MultiTechnologyWeb.Models.loginmodel'.
Header of "register.aspx" page
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/MT.Master" Inherits="System.Web.Mvc.ViewPage<MultiTechnologyWeb.Models.registermodel>" %>
So to my understanding model is being interchanged, so anybody can please help me on how to resolve this issue
More Explanation.............LATEST
I have debug, i know that the crash is occuring after the actionresult for register is finished execution.
Code below is for actionresult "register"
public ActionResult register()
{
registermodel model;
//some code here
return View("register",model);
}
So i'm just returning one type of model that is "registermodel", Would it be possible to return another model such as "loginmodel" by using a list or array to return multiple models in the same view.
You should use <% Html.RenderAction("Logon","Account"); %> in your MasterPage instead of using RenderPartial and in this action you just return the login partial you want to use in the header
public ActionResult Logon(){
// do your stuff
return PartialView("LoginUserControl");
}
By this way you could pass the loginmodel to the LogInPartial and pass registermodel to the register page
Please not that RenderAction and RenderPartial are not the same.
RenderPartial will render only the view. While RenderAction will make a new MVC roundtrip, by making a new instance of the controller etc and returning the result.
To solve your issue you could pass in the MultiTechnologyWeb.Models.loginmodel where you call <% Html.RenderPartial("LoginUserControl"); %>. It would look like this:
<% Html.RenderPartial("LoginUserControl", new MultiTechnologyWeb.Models.loginmodel()); %>
Or:
<% Html.RenderPartial("LoginUserControl", Model.LoginModel); %>
If you're not wanting to send a model to your partial view, which I've wanted to do in the past, you do have to at least pass something to the RenderPartial method.
This was the only method I could find that allowed me to now have to pass a model. I tried passing null and it continued to pass the parent model
<% Html.RenderPartial("LoginUserControl", new ViewDataDictionary()); %>
Hoping someone can help me solve this issue.
I'm using Ajax.BeginForm quite often when I need to update a part of my actual webpage. But if I have a second button in the web form where I need go to a complete different page, and for example do a search and get some values that I need to complete the form. The page turns up in the update panel (updateTargetID) instead of in a complete new View. That is happening even id a do a RedirectToAction in the controller. Of course the ajax.beginform does what I accept it to do, in other words update the panel that shall be updated. But is there a way to get ajax.Beginform to use redirectToaction without updating when the user is choosing to do for example a search instead of sending the form?
I'm working with asp.net MVC,
Problem;
<% using (Ajax.BeginForm(new AjaxOptions() { LoadingElementId = "loadingElement", UpdateTargetId = "SearchResult", InsertionMode = InsertionMode.Replace}))
{%>
<% Html.RenderPartial("Searchfields", Model); %>
<div>
<%:Html.ActionLink("blank", "Index")%>
</div>
<div id="loadingElement" style="display: none">
Load data...
</div>
<div id="SearchResult">
<% if (Model.SearchResult != null)
{
Html.RenderPartial("SearchResult", Model.SearchResult);
} %>
</div>
<% } %>
In the controller (post) I do this among other stuff;
if (Request.IsAjaxRequest())
{
return PartialView("SearchResult", data.SearchResult);
}
But before this I need to do:
if (data.SearchResult.Count() == 1)
{
return RedirectToAction("Edit", "Person", new { Id = data.SearchResult.First).Id});
}
but ofcourse if I do that the hole page i rendered in the corresponding updateTargetId,
I need to render a new view instead. So how can I for exampel use javascript to redirect oncomplete and have the values from the model sent to the script to for exampel do a window.location.replace?
I'm struggling with javascript, so please help me!
I'm following this MVC tutorial and when I add a View for the Edit action, Model is null in the following snippet on the .aspx page:
<%= Html.TextBox("Id", Model.Id) %>
I'm learning MVC, so please understand if I'm doing a dumb thing. But as far as I can see, I've following the steps in the tutorial pretty well. And actually added the Create action and it works correctly.
Ideas appreciated.
Is your view strongly typed?
<%# Page Language="C#" MasterPageFile="~/Views/Shared/TwoColumnUI.Master" Inherits="System.Web.Mvc.ViewPage<MyObject>" %>
then you would need to pass in an object of type MyObject from your controller action method
return View(new MyObject() { Id = 42 } );
Did you set the model in the controller? What does your controller method look like? Are you just returning View()? You need to pass the model as a parameter to that call like they do in the example:
return View(movieToEdit);
Is there a way to make a list of links for each action in controller instead of having to add
<li><%= Html.ActionLink("Link Name", "Index", "Home")%></li>
for each item?
yes there is.
You can either return a SelectList of key value pairs that you can render as anchor tags.
Or you can create a model in the, and this is not the best place for it, controller and return it to the view which you can then itterate through.
public class myAnchorList
{
public string text {get;set;}
public string controller {get;set;}
public string action {get;set;}
}
then in your code create a List<myAnchorList>.
List<myAnchorList> Anchors = new List<myAnchorList>();
Fill the list with data and return.
return View(Anchors).
if you are already passing over a model then you need to add this list into the model you are returning.
Make sense? if not post a comment and i'll try to explain further.
Edit
Let me complete the picture now that i have a little more time.
On the client side you'd have this untested code;
<ul>
<% foreach(myAnchorList item in Model.Anchors){ %>
<li><%= Html.ActionLink(item.text, item.action, item.controller)%></li>
<% } %>
</ul>
In addition to griegs answer, it might be helpful to construct the list of controller actions via reflection. In which case you might want to look at:
new ReflectedControllerDescriptor(typeof(TController)).GetCanonicalActions()
Credit for this answer goes to: Accessing the list of Controllers/Actions in an ASP.NET MVC application
I'm with a problem, I have a ajax link that pass a parameter, but, the page that it opens does not need that parameter. The page only load 2 partial views, one of those need that parameter passed to the page to load the data correctly, and the other just need to load a form, so, don't need that parameter. How can i acheive this?
In order to do what you want, you will need to add the id to the ViewData construct.
var sysfunctions= UnisegurancaService.FunctionsRepository.All();
ViewData["NeededID"] = id
return View(sysfunctions);
then in your view where you render the partial
<%= Html.RenderPartial("GridFunction", (int)ViewData["NeededID"]) %>
Cast as required of course.
Whatever gets pushed in as the second param becomes the .Model in the partial. I would suggest also strongly typing your partials.
Try this:
<% Html.RenderPartial("GridFunction", new ViewDataDictionary {{"Id", ViewData["Id"]}}); %>
UPDATED:
And add this in your controller action:
ViewData["Id"] = Id;
UPDATED:
And in your GridFunction partial View you can access Id as:
<%= ViewData["Id"] %>
//Controller
public ActionResult EditFunctions(int id)
{
var sysfunctions= UnisegurancaService.FunctionsRepository.All();
return View(sysfunctions);
}
// This is the controller (it does no need the parameter "ID")
//This is the view "EditFunctions"
<div id="formFunction">
<% Html.RenderPartial("FormFunction"); %>
</div>
<div id="gridFunction">
<% Html.RenderPartial("GridFunction"); %> // The grid needs the ID to work correctly but its in the parent page not in the partial call....and the call is an ajax call
</div>
If some dependency of the page needs the parameter, then the page needs to know enough to pass the data in, so the page should be able to provide the data. Or, more simply, just add the parameter to the Page's viewdata and be done with it.