MVC Partial view not rendering - asp.net-mvc

I'm new to MVC and I'm trying to add a partial view to my main layout page so I can show messages throughout my app. I'm having some trouble woring it out:
Here's my layout:
<div class="span12">
<p>
#{Html.RenderAction("Messaging", "Messaging");}
</p>
#RenderBody()
</div>
This is my messaging controller:
public ActionResult Messaging()
{
return PartialView(new ViewModels.Messaging()
{
MessageType = Utilities.MessageType.Success,
MessageHeader = "Test",
Message = "this is a test message"
});
}
Here is my partial view called _MessagingPartial.cshtml stored in the shared folder:
#model AWS.PL.ViewModels.Messaging
<span>
Model.Message
</span>
And here is my ViewModel:
public class Messaging
{
public Utilities.MessageType MessageType { get; set; }
public string MessageHeader { get; set; }
public string Message { get; set; }
}
I get the error "Partial view Messaging was not found" error. Should the partial view be called Messanging.cshtml or I'm I get the something fundamentally wrong?
Any help much appreciated.
Thanks,
Wilky.

Here is my partial view called _MessagingPartial.cshtml
Your partial view should be called Messaging.cshtml coz that's the name of the controller action that rendered it.
If you want to render a custom partial name, make sure you explicitly specify that:
public ActionResult Messaging()
{
var model = new ViewModels.Messaging
{
MessageType = Utilities.MessageType.Success,
MessageHeader = "Test",
Message = "this is a test message"
};
return PartialView("_MessagingPartial", model);
}
and if the partial is located in some non-standard location you could also specify the full path to it:
return PartialView("~/Views/FooBar/Baz/_MessagingPartial.cshtml", model);

Your guessing is right. Either partial view should be named after calling action, "Messanging.cshtml" in your case, or you should use overload to explicitly supply view name to View method
protected internal ViewResult View(
string viewName,
Object model
)

Related

How to set a textbox value in a view using a return content of a controller method

I'm totally new to ASP.NET and MVC architecture. I have a controller function and it is something like this.
public ActionResult Calculate()
{
var Message = "Hello There!";
return Content(Message);
}
I need to set this return value to a text box in a view..
if the name of the textbox is "text3", how can I do that?
Thanks in advance.
First, create a ViewModel to hold the message.
public class CalculateViewModel {
public string Message { get; set; }
}
Create a cshtml file to serve as View for this ViewModel. By convention, this file should be named like the action that renders it, i.e. Calculate.cshtml, and be placed in a folder with the name of the controller under Views\.
#model CalculateViewModel
#* render textbox for "Message" property in ViewModel *#
#Html.TextBoxFor(m => m.Message)
Note that this will render an <input name="Message" />. If you want the textbox to be named "text3", the property in the ViewModel should be named "text3" instead of "Message".
In the controller action, return a View with the correctly initialized ViewModel:
[HttpGet]
public ActionResult Calculate() {
var vm = new CalculateViewModel {
Message = "Hello There!";
};
return View("Calculate", vm);
}

MVC4 render item that uses variable?

I am new to MVC, in my View I have :
#{
MyObjectType myNameObject=getMyNameObject();
}
<p>
Name : #myNameObject.firstName
</p>
Trying to implement desing when line "Name : #myNameObject.firstName" comes from database through Model or ViewBag and still pick up value of #myNameObject.firstName. Is that possible?
Thank you
Your Controller action method should get the data and pass it to the View. Using a ViewModel is usually the way to go, but ViewBag also works for one-off data. Something like this:
// View model.
public class MyViewModel
{
public string Name {get; set;}
}
// Controller method.
public ActionResult MyPage()
{
MyViewModel model = serviceLayer.GetMyData();
return View(model);
}
// MyPage View.
#model MyViewModel
<p>Name: #Model.Name</p>
your Model:
public class MyNameObject
{
public MyNameObject()
{
//getvalues from database
//this.FirstName = yourObjectFromDatabase.FirstName;
}
public string FirstName { get; set; }
}
in your views that you want to show the first name:
#using WebApplication1.Models; //put it at the top of the view
#{ Html.RenderPartial("FirstName", new MyNameObject()); }
your view:
#model WebApplication1.Models.MyNameObject
#{
ViewBag.Title = "FirstName";
}
<h2>Name : #Model.FirstName</h2>

Basic Umbraco 6.1.1 SurfaceController Questions

I've searched all the available tutorials I can find, and I'm still having trouble with Umbraco Surface Controllers. I've created a bare-bones Surface Controller example which sorta works, but has some issues. Here's my code so far, questions to follow:
ContactformModel1.cs:
public class ContactFormModel1
{
public string Email { get; set; }
public string Name { get; set; }
public string HoneyPot { get; set; }
public string Title { get; set; }
public string Last { get; set; }
public string First { get; set; }
public string Addr { get; set; }
public string Phone { get; set; }
public string Time { get; set; }
public string Comment { get; set; }
}
ContactSurfaceController.cs:
public class ContactSurfaceController : Umbraco.Web.Mvc.SurfaceController
{
public ActionResult Index()
{
return Content("this is some test content...");
}
[HttpGet]
[ActionName("ContactForm")]
public ActionResult ContactFormGet(ContactFormModel1 model)
{
return PartialView("~/Views/ContactSurface/Contact1.cshtml", model);
}
[HttpPost]
[ActionName("ContactForm")]
public ActionResult ContactFormPost(ContactFormModel1 model)
{
// Return the form, just append some exclamation points to the email address
model.Email += "!!!!";
return ContactFormGet(model);
}
public ActionResult SayOK(ContactFormModel1 model)
{
return Content("OK");
}
}
Contact.cshtml:
#model ContactFormModel1
#using (Html.BeginUmbracoForm<ContactSurfaceController>("ContactForm"))
{
#Html.EditorFor(x => Model)
<input type="submit" />
}
ContactMacroPartial.cshtml:
#inherits Umbraco.Web.Macros.PartialViewMacroPage
#Html.Action("ContactForm", "ContactSurface")
My Questions:
I'm pretty sure that return ContactFormGet(model) is wrong in the
ContactFormPost method, but everything else I've tried throws an error.
When I try return RedirectToCurrentUmbracoPage(), I get Cannot
find the Umbraco route definition in the route values, the request
must be made in the context of an Umbraco request.
When I try return CurrentUmbracoPage(), I get Can only use
UmbracoPageResult in the context of an Http POST when using a
SurfaceController form.
The routing appears to work correctly (when I put a breakpoint inside ContactFormPost, the debugger stops there). But when the form comes back, I get the exact values I submitted. I don't see the !!! appended to the email address. (Note, this bit of code is just for debugging, it's not meant to do anything useful).
How do I call the "SayOK" method in the controller? When I change the BeginUmbracoForm method to point to SayOK, I still get stuck in the ContactFormPost method.
I'm sure I'm missing something incredibly stupid, but I can't figure this out for the life of me.
I wanted to take a moment to say how I resolved this. After playing around some more, I realized that I didn't really state my problem clearly. Basically, all I'm trying to do is embed an MVC form inside a Partial View Macro, so that it could be used in the content of a page (not embedded in the template).
I could get this solution to work, but I really didn't like how much logic the author put inside the View file. So I adapted his solution this way:
Partial View Macro (cshtml) file:
#inherits Umbraco.Web.Macros.PartialViewMacroPage
#using Intrepiware.Models
#{
bool isPostback = !String.IsNullOrEmpty(Request.Form["submit-button"]);
if(isPostback)
{
#Html.Action("CreateComment", "ContactSurface", Request.Form)
}
else
{
#Html.Partial("~/Views/Partials/ContactForm.cshtml", new ContactFormModel())
}
}
Form Partial View (cshtml) file:
#using Intrepiware.Models
#using Intrepiware.Controllers
#model ContactFormModel
<p>
<span style="color: red;">#TempData["Errors"]</span>
</p>
<p>
#TempData["Success"]
</p>
<div id="cp_contact_form">
#using(Html.BeginUmbracoForm("CreateComment", "BlogPostSurface"))
{
#* Form code goes here *#
}
ContactSurfaceController.cs file:
public class ContactSurfaceController : Umbraco.Web.Mvc.SurfaceController
{
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult ubCreateComment(ContactFormModel model)
{
if (processComment(model) == false)
return CurrentUmbracoPage();
else
return RedirectToCurrentUmbracoPage();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult CreateComment(ContactFormModel model)
{
if(processComment(model) == true)
{
TempData["Success"] = "Thank you for your interest. We will be in contact with you shortly.";
ModelState.Clear();
}
return PartialView("~/Views/Partials/ContactForm.cshtml");
}
private bool processComment(ContactFormModel model)
{
// Handle the model validation and processing; return true if success
}
}
The controller is designed so that the form can be embedded either in the template or a Partial View Macro. If it's embedded in a template, the form should post to ubCreateComment; if it's in a macro, post to CreateComment.
I'm almost positive there's a better/more correct way of doing this, but I ran out of time to work on the project. If someone has a better solution, please post it!
One final question/note: You'll notice that the partial view macro posts Request.Form to the ContactSurfaceController.CreateComment, and MVC magically serializes it for me. That's safe, yeah? If so, doesn't MVC rock? :)
You are using a ChildAction because you are specifying #Html.Action("ContactForm", "ContactSurface") and because of this, in your View you need to:
Use Html.BeginForm(...) and not 'Html.BeginUmbracoForm(...)'
Allow the form to post back to the same path and not to the action
If you do this, then the form will post back to itself as expected.
See the documentation here for further help.
Edit:
Just saw the final part to your question. If you intend SayOK to be your 'thank you' message, I would just call it from your HttpPost action instead of returning the initial view.

Handling ActionResult from inside the view

Describing my scenario will be the best way to describe what I'm trying to achieve. I'm looking for a cleaner solution, if it exists at all.
We have content that would like to lock. I abstracted the unlocking models because we could have different types. It could be a Redirect or rendered partial view or something else they could come up in the future, so I decided to try returning an ActionResult.
public abstract class AContentUnlocker
{
public abstract ActionResult GetUnlockActionResult();
}
public class RedirectUnlocker : AContentUnlocker
{
public override ActionResult GetUnlockActionResult()
{
return new RedirectResult("http://www.url1.com?returnUrl=mywebsiteagain");
}
}
public class PartialViewUnlocker: AContentUnlocker
{
public override ActionResult GetUnlockActionResult()
{
PartialViewResult view = new PartialViewResult();
view.ViewName = "_PartialViewToUnlock";
return view;
}
}
My Content would be represented in a model with the proper Unlocking Mechanism
public class MyContent
{
public string Description { get; set; }
public AContentUnlocker ContentUnlocker { get; set; }
}
In my controller, I would simply return my desired Content with the proper unlocking mechanism set.
public ActionResult Index()
{
MyContent myContent = new MyContent() {
Description = "Content 1",
ContentUnlocker = new PartialViewUnlocker()
};
return View(myContent);
}
In my index View, I would then Execute the ActionResult.
#{
Model.ContentUnlocker.GetUnlockActionResult().ExecuteResult(this.ViewContext);
}
return View(myContent);
The Redirect ActionResult works fine.
My problem is that with the Partial View Action Results, given the execution cycle of MVC, the partial view is rendered before the controller view. So I'm getting something like:
<!-- html of the partial view rendered -->
<div> blah blah </div>
<!-- html of the parent view -->
<html>
<head></head>
<body> blah .... </body>
</html>
I'm not sure it's possible, but is there a way to execute my ActionResult the same way Html.RenderPartial would?

ASP.NET MVC Masterpage code file

Please can anybody point out where this code might be going wrong. I am trying to create a partial class for the masterpage.
The master pages class:
namespace MuniWeb.Models.SiteMaster{
public class BaseViewData
{
public string Title { get; set; }
public string MetaKeywords { get; set; }
public string MetaDescription { get; set; }
}
public partial class Site : System.Web.Mvc.ViewMasterPage<MuniWeb.Models.SiteMaster.BaseViewData>
{
public Site()
{
ViewData.Model = new BaseViewData();
}
}}
The master page:
<%# Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage<MuniWeb.Models.SiteMaster.BaseViewData>" %>
The error:
Object reference not set to an instance of an object.
Line 33: <div id="footer">
Line 34: ApplicationID:
Line 35: <%= Model.Title %>
Line 36: </div>
Line 37: </div>
I am just using this as an example. The code I want to use needs to fire for every page to check certain parameters, this is why it is in the master page.
You shouldn't need to make a partial class. What does your controllers action code look like? The error looks like it could be from not handing the View (and therefore it's master page) a model.
Try something like this:
namespace MuniWeb.Website.ViewDataModels {
public class BaseViewData
{
public string Title { get; set; }
public string MetaKeywords { get; set; }
public string MetaDescription { get; set; }
}
public class SubViewData : BaseViewData
{
public IList<Thing> Things { get; set; }
}
}
Then define your master page like you had:
<%# Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage<MuniWeb.Website.ViewDataModels.BaseViewData>" %>
Now in your controller
public ActionResult Index()
{
SubViewData viewData = new SubViewData();
viewData.Title = "Page Title";
viewData.MetaKeywords = "This, that, and the other";
viewData.MetaDescription = "A really great page about this, that, and the other.";
viewData.Things = _myRepository.GetThings();
return View(viewData);
}
See how that goes...
I would ask why the MasterPage NEEDS strongly type ViewData. I understand that yes, sometimes strongly typed viewdata is needed in masterpages but generally you should be able to get way with just using the ViewData name value collection.
Shouldn't your master page be inheriting Site and not System.Web.Mvc.ViewMasterPage? No where does your master page definition actually reference the Site class.
In your code,
public partial class Site :
System.Web.Mvc.ViewMasterPage<MuniWeb.Models.SiteMaster.BaseViewData>
{
public Site()
{
ViewData.Model = new BaseViewData();
}
}}
ViewData.Model = new BaseViewData(); is not necessary. The BaseViewData should be passed in via the controller. In other words, all of your views should take look for a View that inherits the base view. The Master Page will have that same object cast as the base class BaseViewData. Your controller code appears to be correct in doing just that.
Another thing that appears to be different from my similar code is Inherits=System.Web.Mvc.ViewMasterPage<MuniWeb.Models.SiteMaster.BaseViewData> should be Inherits=my.codebehind.class, then your codebehind would inherit ViewMasterPage<MuniWeb.Models.SiteMaster.BaseViewData>.
I've just not seen the code as such, perhaps it works?

Resources