Use a Action Function from controller in umbraco8 - c#

i'm creating a new website with umbraco8 i have a problem how to load an Action in Controller from a view of Homepage
Homepage view
#inherits Umbraco.Web.Mvc.UmbracoViewPage<ContentModels.HomePage>
#using ContentModels = Umbraco.Web.PublishedModels;
#{
Layout = "webBase.cshtml";
}
#{ Html.RenderAction("RenderHomeSlider", "HomePage"); }
Homepage Controller
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Umbraco.Web.Mvc;
using System.Web.Mvc;
using Umbraco.Core.Models;
using HAWELE.Models;
using Archetype.Models;
using Umbraco.Web;
using System.Threading;
using Umbraco.Web.Mvc.SurfaceController;
public class HomePageController : Umbraco.Web.Mvc.SurfaceController
{
public ActionResult Index(RenderModel model)
{
return base.Index(model);
}
private const string PARTIAL_VIEW_HOME_FOLDER = "~/Views/Partials/HomePage/";
public ActionResult RenderHomeSlider(this HtmlHelper html)
{
return PartialView(PARTIAL_VIEW_HOME_FOLDER + "_HomeSlider.cshtml");
}
}

The issue isn't related to Umbraco. [ChildActionOnly] attribute is missing on the calling method:
RenderAction(HtmlHelper, String, String)
Invokes the specified child action method using the specified controller name and renders the result inline in the parent view.
https://learn.microsoft.com/en-us/dotnet/api/system.web.mvc.html.childactionextensions.renderaction?view=aspnet-mvc-5.2

Try the following:
Remove the index method from your controller. It is not relevant in a surfacecontroller.
Modify the RenderHomeSlider Action to:
public ActionResult RenderHomeSlider()
{
return PartialView(PARTIAL_VIEW_HOME_FOLDER + "_HomeSlider.cshtml");
}
This line in your view
#{ Html.RenderAction("RenderHomeSlider", "HomePage"); }
should change to
#Html.Action("RenderHomeSlider", "HomePage")
This should render whatever html is in _HomeSlider.cshtml
It's not clear whether your _HomeSlider.cshtml partial requires any model to be passed into so I am assuming it doesn't.
To test that the above works, you can just put some simple text in your partial and see if it rendered on the page.
I don't know what the rest of your code looks like so can't say exactly whether what you are trying to achieve here is the most expedient way to do it.
Good luck

Related

Razor equivalent of FromQuery attribute

I'm trying to build a simple page with a simple form with ASP.NET using a Razor page, and can't work out how to handle a particular post-back. In particular (through factors outside of my control) I'm getting a post-back with a single query parameter that is lowercase and kebab-case, in a regular MVC page I could use the FromQuery attribute, but it doesn't appear to work in this instance as with or without the attribute I get null passed to OnPostAsync each time. An example to illustrate this issue follows:
Example.cshtml
#page
#model my_namespace.Pages.ExampleModel
#{
ViewData["Title"] = "Example Title";
}
<h2>Example</h2>
<form method="post">
<!--- In actual code I don't have control of the name, so this is for illustrative purposes. --->
<input type="text" name="kebabbed-name"/>
<input type="submit" />
</form>
Example.cshtml.cs
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace my_namespace.Pages
{
public class ExampleModel : PageModel
{
public async Task<IActionResult> OnGetAsync()
{
return Page();
}
// This method is hit as expected, but the parameter is always null.
// Changing the input name to something like "sample" and this parameter to match works however.
public async Task<IActionResult> OnPostAsync(string kebabbedName)
{
// Handling of the Post request
return Page();
}
}
So what I'm looking for is some way to process the postback with that kebabbed-name as a parameter - any solution would be welcomed.
It doesn't seem like Razor pages could process kebabbed-names automagically, however you can create a property in your PageModel class with a custom name that should bind to the postback value.
// For GET request
// [BindProperty(Name = "kebabbed-name", SupportsGet = true)]
// For POST request
[BindProperty(Name = "kebabbed-name")]
public string kebabbedName { get; set; }

How to manipulate data from HTML input tag with ASP.NET MVC

I'm trying to create a web application using ASP.NET MVC (though I'm still a beginner so I don't know much about C#, I only used VB.net). I want my ASP.NET MVC application to store the content of the HTML input tag like username and password to sign in to my application but it didn't work out.
(PS : I'm still a beginner so please make it as simple as it can get)
I already tried many tutorials before coming here, but none of them seems to work.
Here's is the code I tried
// in the Model:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace MoviesApp.Models
{
public class Movie
{
public string id { get; set; }
public string name { get; set; }
}
}
// in the controller
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MoviesApp.Models;
namespace MoviesApp.Controllers
{
public class MoviesController : Controller
{
// GET: Movies
public ActionResult Random(string movieid, string moviename)
{
var movie = new Movie();
movie.id = movieid;
movie.name = moviename;
return View(movie);
}
}
}
//in views :
#model MoviesApp.Models.Movie
#{
ViewBag.Title = "Random";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<form method="post" action="Random">
<input type="text" name="movieid"/>
<input type="text" name="moviename"/>
<input type="submit" value="save" />
</form>
I think action should look like this. And [HttpPost] in the controller
<form method="post" action="/Movies/Random">
Please try adding this to your controller method (you use POST instead of GET in your client side code):
[HttpPost]
public ActionResult Random(string movieid, string moviename)
{
var movie = new Movie();
movie.id = movieid;
movie.name = moviename;
return View(movie);
}
The default MVC controller route defined in App_Start/WebApiConfig.cs is
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Hence, call controller method as following
https://localhost:44397/Movies/Random?movieid=Shrek&moviename=first
Get vs Post
I think it worked since my link changed to :
https://localhost:44397/Movies/Random?movieid=Shrek&moviename=first
but my method is now get and the attribute is httpget insted of httppost would you please explain what post and get are and when should i use post or get ?
PS: when i added httppost to the controller and set the method to post and the action to /MoviesController/Random it gave me the error ressouce cannot be found

ModelState.IsValid always evaluating as true when working with FluentValidation

I am a junior programmer trying to write a simple little bit of code to test out FluentValidation, but without manually calling the validator and adding the results to the modelstate with .AddToModelState, I cannot get the ModelState.IsValid to recognize there are errors in the validation. Am I missing integration somewhere?
This is my Value Model, just a string array with two preset values.
using FluentValidation.Attributes;
using Playground2.Validators;
namespace Playground2.Models
{
[Validator(typeof(ValueValidator))]
public class Value
{
public string[] values = { "value1", "" };
}
}
This is my Validator, looking for two values between 5 and 10 characters.
using FluentValidation;
using Playground2.Models;
namespace Playground2.Validators
{
public class ValueValidator : AbstractValidator<Value>
{
public ValueValidator()
{
RuleFor(x => x.values[0]).Length(5, 10);
RuleFor(x => x.values[1]).Length(5, 10);
}
}
}
In the ValuesController, I am simply creating a value object and running a check to see if it passes validation before being output.
using FluentValidation.AspNetCore;
using Microsoft.AspNetCore.Mvc;
using Playground2.Models;
using System.Collections.Generic;
namespace Playground2.Controllers
{
[Route("api/[controller]")]
public class ValuesController : Controller
{
// GET api/values
[HttpGet]
public IEnumerable<string> Get()
{
var value = new Value();
if (!ModelState.IsValid)
{
return new string[] { "Not valid" };
}
else
{
return value.values;
}
}
But when run, the ModelState.IsValid is always evaluating as true, though the information fed into values is by default invalid.
FluentValidation follows MVC's/HTML's convention in regard to GETs and POSTs. In this case it's not expecting any validation to be done an a page's initial GET as a user wouldn't necessarily have performed any action. They're instead requesting the page to start doing something - they haven't gotten around to supplying data.
Once the user fills out information the convention is to submit the data in a HTML <form> using a <button> or <input type="submit"/> to submit the data to the controller via a HttpPost marked method. At this point validation has triggered and you'll be able to correctly interrogate the ModelState.IsValid.

Asp.net MVC binding to view model

Current Situation: Starting with ASP.net MVC development and coming from MVVM app development I'm struggling with the binding of a view with view model / controller. I started with an empty project and tried to create model, viewmodel, controller and view. Starting the project I get a "500 Internal server error" but don't understand what's wrong (no error in the output window). I just can't understand how a view actually binds to a view model (probably because I think too much in MVVM).
What I currently have:
Startup.cs:
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Hosting;
using Microsoft.Extensions.DependencyInjection;
namespace WebApplication1
{
public class Startup
{
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app)
{
app.UseIISPlatformHandler();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Sample}/{action=Index}/{id?}");
});
}
// Entry point for the application.
public static void Main(string[] args) => WebApplication.Run<Startup>(args);
}
}
Model:
using System;
namespace WebApplication1.Models
{
public class SomeModel
{
public string Title { get; set; }
public DateTime Time { get; set; }
}
}
ViewModel:
using System;
using System.Collections.Generic;
using WebApplication1.Models;
namespace WebApplication1.ViewModels
{
public class SampleViewModel
{
public IList<SomeModel> SomeModels { get; set; }
public SampleViewModel()
{
SomeModels = new List<SomeModel>();
SomeModels.Add(new SomeModel()
{
Time = DateTime.Now,
Title = "Hallo"
});
}
}
}
Controller:
using Microsoft.AspNet.Mvc;
using WebApplication1.ViewModels;
namespace WebApplication1.Controllers
{
public class SampleController : Controller
{
//
// GET: /Sample/
public IActionResult Index()
{
return View(new SampleViewModel());
}
}
}
View:
#model WebApplication1.ViewModels.SampleViewModel
<!DOCTYPE html>
<html>
<head>
<title>Hallo</title>
</head>
<body>
#foreach (var someModel in Model.SomeModels)
{
<div>#someModel.Title</div>
}
</body>
</html>
I found a lot of articles talking about model binding but they only talk about forms and input. What I want is to show some data, e.g. from a database in some kind of list or so and therefore don't need to post any date to the website.
Does anyone see the (probably obvious) issue in my sample code?
The project is based on ASP.net 5 MVC 6 using DNX.
I already set some breakpoints to see whether the controller is actually called. And it is. I went through the few methods with the debugger without any issue. Also, the output window does not show any error or sth. like that.
The view name was missing in the result for the GET method. So instead of
return View(new SampleViewModel());
it must be
return View("Sample", new SampleViewModel());
I thought that the connection between view and controller is purely convention based. So a controller named Sample searches for a view named Sample in a folder called Sample which in turn is a subfolder of Views.
Not sure exactly why, but it works this way.

Adding a View to a Webforms Website/MVC project

I have an asp.net Webforms website that I'm trying to integrate MVC to. I'm almost there, but I'm having some problems.
What I did so far:
Added references to:
System.Web.Routing
System.Web.Abstractions
System.Web.Mvc
Updated the root Web.config to load the three assemblies at run time.
Added directories:
Views
App_Code\Controllers
Updated the Global.asax and configured routing:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
}
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("{resource}.aspx/{*pathInfo}");
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" }
);
}
So far so good.
I right-click the Controllers folder, add a "HomeController", like this, run the website and it works!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
public class HomeController : Controller
{
public string Index()
{
return "This is my <b>default</b> action...";
}
public string Welcome()
{
return "This is the Welcome action method...";
}
}
Now the problem:
I update the HomeControler to use a View, like this, but it doesn't work.
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
}
To create the view, I created a directory inside "Views" called "Home". Inside "Home" I added a new "Empty Page (Razor v3)", called "Index.cshtml":
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>View Template!</p>
The first problem is with this line:
ViewBag.Title = "Index";
VS indicates that "The name 'ViewBag' does not exist in the current context
The second problem is that when I run the website, I get the following error message:
The view 'Index' or its master was not found. The following locations
were searched: ~Views/Home/Index.aspx ~Views/Home/Index.ascx
~Views/Shared/Index.aspx ~Views/Shared/Index.ascx
I know it is possible to integrate a Webforms website with MVC pages.
It appears like my configuration is correct. I can successfully add a Controller and get the desired result.
BUT, how do I get my Controller to use a View?

Categories

Resources