Pass model from strongly typed view back to a controller action - mvc2 VB.net - asp.net-mvc

Here's what I have. I have an MVC application where all the data is tied together by VisitDate table in my database. The home page is a strongly typed view of type VisitDate, all it does is pull up some simple data. Now, here's where I'm having a problemo. I need a link that passes the current model in the view back to a seperate controller action so I can render a different page with different data.
Here are my two controller actions. I'm going from News.aspx to FrontPage.aspx and hopefully passing SchoolVisit.
Function News(ByVal SchoolVisit As SchoolVisitDate) As ActionResult
Dim db As New NewsData.NewsDB
Dim repos As New NewsRepository
Dim _classId As Integer
_classId = (From a In db.SchoolClasses Where a.VisitDateID = SchoolVisit.VisitDateID Select a.ClassID).Single()
ViewData("VisitDate") = FormatDateTime(SchoolVisit.VisitDate, vbShortDate)
ViewData("Staff") = repos.GetStaff(_classId)
ViewData("StockArticles") = From a In db.StockArticles Select a
ViewData("Articles") = repos.GetArticles(_classId)
Return View()
End Function
Function FrontPage(ByVal SchoolVisit As SchoolVisitDate) As ActionResult
Dim repos As New NewsRepository
Dim _VisitDateID As Integer
_VisitDateID = SchoolVisit.VisitDateID
ViewData("Editorial") = repos.GetEditorial(_VisitDateID)
Return View()
End Function

Html.ActionLink can be of help

Here's what you have to do:
You should make the News view strongly typed for SchoolVisitDate.
Have a form that submits the strongly typed SchoolVisitDate stuff post back to controller
Add a Post method to your controller
Have that post method redirect to the FrontPage view.

Related

Pass variables to a partial view in MVC

How can I send variables to my partial view?
And I don't mean like my model, but values seperate from that
So instead of #Html.Partial("~/Views/Test/_Partial.cshtml", Model)
It would be something like #Html.Partial("~/Views/Test/_Partial.cshtml", Variable = 2)
And then in my partial view I could just use it like
// html
#Variable
// html
You can make the model of your partial the type you want to pass to it:
#model int
In the parent view:
#Html.Partial("~/Views/Test/_Partial.cshtml", 2)
Then access it from the partial view as #Model.
Following are the available options to pass data from a Controller to View in ASP.NET MVC which would be appropriate in your case:
ViewBag
ViewData
TempData
If we want to maintain state between a Controller and corresponding View- ViewData and ViewBag are the available options but both of these options are limited to a single server call (meaning it’s value will be null if a redirect occurs). But if we need to maintain state from one Controller to another (redirect case), then TempData is the other available option which will be cleared once hit.
public ActionResult Index()
{
ViewBag.EmployeeName = “Tushar Gupta”;
return View();
}
View
<b>Employee Name:</b> #ViewBag.EmployeeName<br />

How can I implement a copy action that reuses the create and edit views?

I want to be enable my user to click on an existing entity with, say, Id=123, fetch and copy that object, and then let the user edit it and create a new object using the same view that I'm using to create or edit. I tried the following action method:
' GET: /controller/copy/id
Function Copy(ByVal id As Integer) As ActionResult
Dim obj = db.MyTable.Find(id)
If obj.IsNothing() Then
Return HttpNotFound()
End If
'blank out the id to flag that this is a new entity
obj.Id = 0
'reuse the editing view
Return View("Edit", obj)
End Function
This renders fine, but the form HTML looks like this:
<form action="/Controller/Copy/123" method="post">
And when I post back, the passed model object has Id=123, same as the object being copied. I think this must be because the route /Controller/Copy/123 has the id in the third position, and model binding sees this.
So, how should I implement Copy so that I can copy object 123 but then forget all about that id, to avoid this problem? If there's an entirely different design pattern I should be using, that's fine too.
Override the form action to be "". This means that the current URL will be used.
If i understood you right.... just set id to null or to 0 in form routeValues property
In razor using c#
#using (Html.BeginForm("copy", "controller", FormMethod.Post, new { id = null /* or = 0 */ }))
// form code
In controller:
public ActionResult Copy(int? Id)
// action code

ASP .NET MVC How to pass data between views

I have this scenarion.
There are Boards. And Threads. Therads can be created only on boards, and for that they need to be provided with board ID, Name or something like that, to let SQL know where it should add thread.
By now I've been using hidden fields to pass data between views, but more I used them tehre was more trash in code like ViewBags, unnesseary attributes in methods etc.
Are there cleaner ways to do it ?
Pass the model back to the view.
so if you have a model called Data with a field called Name then;
Data fvm = new Data{ Name = "my name"};
return View(fvm)
then inherit the view from the model and use;
<%= Model.Name %> to get data.
Then as you move from view to view you pass the form back to the view with either ajax, jQuery submit plugin or a submit button which should also be the model.
then in your controller;
public actionresult myciew(Data model)
{
//do something with the model
}

ASP.NET MVC2: Views, Viewmodels, and Post requests

I am having trouble following good object-oriented design in ASP.NET MVC2 and I think the problem is a poor understanding of how ViewModels and Views should interact when the user will be posting information.
I have implemented a forum that allows users to create replies to a thread using a Reply action. My ReplyViewModel contains an int for the threadId and a string for the reply's content. The Reply action creates a ReplyViewModel with the ThreadId so we'll know to which thread the user is replying. The Reply View is strongly typed to the ReplyViewModel and has a form allowing the user to edit the model's content. The user can then post to the Reply action with the threadId as a parameter.
It works, but I don't think I'm doing this the correct way. Each post involves two ReplyViewModels: one with the threadId but null content, and the other with content but a null ThreadId. The Reply View is creating a new ReplyViewModel, and I think it should just be editing the ReplyViewModel that was passed to the view--but I don't know how.
Here's a stripped-down version of the view:
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<mvcForum.ViewModels.ReplyViewModel>" %>
<%: Html.TextAreaFor(model=> model.content, new{TextMode="multiline", id="postbox"})%>
<input type="submit" value="Reply" />
In case that's not enough to answer my question, here's the entire view: http://pastebin.com/BFGL4p67
The ViewModel is literally just a string (content) and an int (threadId).
The controller:
[Authorize]
public ActionResult Reply(int id)
{
ReplyViewModel reply = new ReplyViewModel
{
ThreadId = id
};
return View(reply);
}
[HttpPost]
public ActionResult Reply(int id, ReplyViewModel model)
{
/**TODO: Catch when no user*/
var newPost = new ForumPost
{
UserId = (Guid)Membership.GetUser(User.Identity.Name).ProviderUserKey,
ThreadId = id,
postContent = model.content
};
db.AddToForumPosts(newPost);
db.SaveChanges();
return RedirectToAction("Index");
}
So my question is "What's the best way to do what I'm trying to do? Can I use a single instance of the ReplyViewModel to pass from the controller, to the view, and back to the controller?"
I think what you're doing is fine.
You're thinking about a problem that you haven't come across yet, which is when the data to populate the form differs greatly from the data that will be posted. Here the 'Get' view model is a subset of the 'Post' view model, so using one view model is fine, but if the data for the 'Get' and the data for the 'Post' differed greatly, you could use two different view models such as:
public class GetReplyFromViewModel //...
public class PostReplyFromViewModel //...
But I would suggest against this unless both view models were very different and sufficently complex to require their own view models.
One important thing to remeber: just because the view is strongly typed to type 'A' doesn't mean the type of the parameter in the post method can't be type 'B'.
The type of the View will simply determine the compilation / intellisense in the view along with the type checking of the view whenever one is created.
The type of the post method parameter will simply use the MVC Model Binding to convert the posted HTTP form to the type you specify.
In other words the type of your view could simply be
<%# Page Title="" ... Inherits="System.Web.Mvc.ViewPage<int>" %>
Where the whole Model variable is simply the ThreadId if you like and the post method could still take the same parameter if your html fields were named properly.
but again, in this particular case I think the current implementation is just fine.

Function in ASP.NET MVC

A function returns only one view.
what if I want to return multiple views in a function?
For example, I have this code:
Function Index() As ActionResult
Dim _news As DataTable = News.newsSelect()
Dim _announcement As DataTable = Announcement.SelectAnnouncement()
Return View()
End Function
I want to return _news and _announcement to be used in the aspx page. How would I do this?
Are you trying to show both sets at the same time? News and Announcements?
If so then why not implement either a PartialView or two PartialViews?
Then in your main view you can render them and pass the collection to the PartialViews?
There are heaps of samples on this and the one I recommend is in NerdDinner if you haven't already seen it.
I hope this helps. If you want sample code then let me know.
One simple way is just to have those two datasets sent in a ViewData element, which you can access in a field.
example:
ViewData["Elements"] = new SelectList(aElements, "Guid", "Name");
is consumed as:
<%= Html.DropDownList("Elements","Pick an element")%>
Also, I think that if you read between the lines of this blog post here you will find an elegant way of achieving what you want ;) but its a bit more involved..(only because you mentioned Views instead of just variables..
Quote:
We need to create our own implementation of IViewFactory. This
is responsible for locating and
creating an instance of an IView
(which both ViewPage and
ViewUserControl implement).
To “inject” (all you DI fans excuse me borrowing the term without
using a DI framework) our new View
Factory into every Controller we are
going to create our own
IControllerFactory implementation.
We need to configure the framework to use our new Controller
Factory.
Finally we can create two Views – an AJAX version and a pure
HTML version.
Building on that should be all you need
Good luck!
Ric
Assuming what you are trying to do is use both of those DataTables to populate some View, then my recommendation would be to create a wrapper object and then a strongly typed view based on this object.
The wrapper object would contain properties for all of the data elements that you need in order to render your view properly. In your case, it is 2 DataTable objects. I do not really know VB, so all my examples will be in C#. Here is an example of the data wrapper class...
public class IndexViewData
{
public DataTable News { get; set; }
public DataTable Announcement { get; set; }
}
You then might update the Index action in your controller as follows:
public ActionResult Index()
{
var viewData = new IndexViewData();
viewData.News = News.newsSelect();
viewData.Announcement = Announcement.SelectAnouncement();
return View(viewData);
}
Finally, you would need to create/update your view to be strongly typed. This is done by having your page inherit from the generic System.Web.Mvc.ViewPage<T> class. Just substitute the view data wrapper created earlier for T. To do this, you would set the inherits attribute of the <%# Page %> element. In your case, if we assume your root namespace is called "Foo", you might have the following page declaration in your Index.aspx view (added extra line breaks for readability):
<%# Page Title=""
Language="C#"
MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<Foo.Models.MyModelType.IndexViewData>"
%>
Once you have a strongly typed view for your view data wrapper, you can access the wrapper object in your view using the Model property. Here is an example of something you could do in your Index.aspx view
<%-- Output some random data (bad example, for demonstration only) --%>
<%= Model.News[0]["title"] %><br/>
<%= Model.Anouncement[0]["body"] %>
In reality you're probably going to do something like iterate over each row of the data table. Regardless, once you create the strongly typed view, your model object, which was passed to the view in the Index method of the controller, is available in the Model property within the view.
You can find detailed tutorials at the ASP.NET MVC site

Resources