asp.net core render a view into stringwriter - asp.net-core

So I want to build an Html custom builder which passes a model object to a partial view and renders the page into a StringWriter
public static class HtmlExtensions
{
public static HtmlString BuildTextboxFor(this IHtmlHelper helper, object model)
{
//Find the partial view and pass the Model through it.
//Render the page into a StringWriter
//return new HtmlString(StringWriter object);
}
}
The models name will be the name of the partial. I can't seem to find a solution for .NET CORE. All the resources seem to be for ASP.NET Framework.

IHtmlHelper.Partial returns IHtmlContent, HtmlString is just another implementation of the same abstraction. Looking at your sample code this is the desired result (not a StringWriter)
public static HtmlString BuildTextboxFor(this IHtmlHelper helper, object model) {
return helper.Partial($"~/Views/{model.GetType().Name}.cshtml", model)
}
If you still want to write the view to a StringWriter its not a problem:
var content = helper.Partial($"~/Views/{model.GetType().Name}.cshtml", model);
using(var writer = new StringWriter()) {
content.WriteTo(writer, HtmlEncoder.Default);
}

Related

How return a yaml file as result of an asp.net core ViewComponent

I want to create an asp.net core ViewComponent that dynamically return a yaml file based on some criteria:
For example
namespace MyNameSpace {
[ViewComponent(Name = nameof(MyViewComponent))]
public class MyViewComponent : ViewComponent
{
public async Task<IViewComponentResult> InvokeAsync(object input)
{
string yamlDocument = GetYamlDocumentByInput(input);
//how to proceed here so that my yamlDocument is returned with the right content type?
return View(..., yamlDocument);
}
}}
you could search the view component class,and there‘s no method can return a file as result.
you'd better add an action in your controller to download file,and you could send a request to this action after your view has been rendered mannully or automaticlly.
and there's the codes in the action:
public FileResult DownLoad(Person person)
{
var serializer = new SerializerBuilder()
.WithNamingConvention(CamelCaseNamingConvention.Instance)
.Build();
var yaml = serializer.Serialize(person);
byte[] yamlArray = System.Text.Encoding.UTF8.GetBytes(yaml);
return File(yamlArray, "application/x-yml");
}
Result:

Getting Error in using View and ViewData in .NetCore 2.2 Project --

a quick question. I am getting following error when trying to return view from my controller method.
The name View does not exist in current context
refer this pic to understand my project structure -- https://pasteboard.co/Jh1AxGy.png
My code is
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using AutoMapper;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Authorization;
using CoreSpeechService.App.Utility;
public IActionResult ProductInfo(int p_id)
{
if(p_id>0)
{
var pEntity = pService.GetProductById(p_id);
if(pEntity!=null)
{
ViewData["ProductId"] = pEntity.Id;
return View(pEntity);
}
else
{
return RedirectToAction("Index");
}
}
else
{
return BadRequest("Could not fetch detailes related to this product at the moment. Please try later.");
}
}
One would have thought I have added all necessary namespaces in controller. Apparently not. I have a hunch it is mostly due to my project structure [the controller and cshtml files]. Proper scaffolding issue? What
should be done?
Suggestions. Thanks
** worth mentioning - my controller is inherited from ControllerBase and not Controller.
The name View does not exist in current context
That is because your controller inherits from ControllerBase.You could check the source code below,ControllerBase does not contain View() method by default.Controller inherits from ControllerBase and add view support:
//A base class for an MVC controller with view support.
public abstract class Controller : ControllerBase, IActionFilter, IFilterMetadata, IAsyncActionFilter, IDisposable
{
protected Controller();
// Summary:
// Creates a Microsoft.AspNetCore.Mvc.ViewResult object that renders a view to the
// response.
//
// Returns:
// The created Microsoft.AspNetCore.Mvc.ViewResult object for the response.
[NonAction]
public virtual ViewResult View();
//
// Summary:
// Creates a Microsoft.AspNetCore.Mvc.ViewResult object by specifying a viewName.
//
// Parameters:
// viewName:
// The name or path of the view that is rendered to the response.
//
// Returns:
// The created Microsoft.AspNetCore.Mvc.ViewResult object for the response.
[NonAction]
public virtual ViewResult View(string viewName);
//
// Summary:
// Creates a Microsoft.AspNetCore.Mvc.ViewResult object by specifying a viewName
// and the model to be rendered by the view.
//
// Parameters:
// viewName:
// The name or path of the view that is rendered to the response.
//
// model:
// The model that is rendered by the view.
//
// Returns:
// The created Microsoft.AspNetCore.Mvc.ViewResult object for the response.
[NonAction]
public virtual ViewResult View(string viewName, object model);
//
// Summary:
// Creates a Microsoft.AspNetCore.Mvc.ViewResult object by specifying a model to
// be rendered by the view.
//
// Parameters:
// model:
// The model that is rendered by the view.
//
// Returns:
// The created Microsoft.AspNetCore.Mvc.ViewResult object for the response.
[NonAction]
public virtual ViewResult View(object model);
}
From your such scenario,just change ControllerBase to Controller:
public class ProductController : Controller { }
Besides,I see your structure contains Razor Pages.When you use return View(model),it would render the razor view with the model data.Be sure you have a razor view named ProductInfo.cshtml instead of a razor pages named ProductInfo.cshtml.

How to retrieve current application root URL in .net core within a static method?

I am currently using the Request.Scheme and Request.Host to composite Uri object to get AbsoluteUri for my .net core MVC application.
Uri location = new Uri($"{Request.Scheme}://{Request.Host}");
string applicationRootURL = location.AbsoluteUri;
But this only works in a non-static method.
As I need to re-use this method in another controller, I am thinking to make this action method static. If I do that, the compiler will complaint about the Request.Scheme and Request.Host.
I am wondering what's other options I have to achieve this?
Thank you.
UPDATE:
This is what I have for ControllerA with ActionMethodA
public class ControllerA
{
public bool ActionMethodA()
{
Uri location = new Uri($"{Request.Scheme}://{Request.Host}");
string applicationRootURL = location.AbsoluteUri;
return false;
}
}
And in another ControllerB, I want to ActionMethodB to invoke ActionMethodA from ControllerA:
public class ControllerB
{
public void ActionMethodB()
{
var result = ActionMethodA();
}
}
Is creating an Extension Method to the ControllerA is the most proper way to handle this kind of scenario?
Thank you.
You can also define an extension method directly for the HttpRequest class and use the BuildAbsolute method of the UriHelper class to build the uri.
public static class HttpRequestExtensions
{
public static string GetURI(this HttpRequest request)
{
return UriHelper.BuildAbsolute(request.Scheme, request.Host);
}
}
And use it:
public IActionResult ContollerMethod()
{
var uri = Request.GetURI();
// your code
}
You can write an extension method to a controller or HttpContext object. In the following example I have added an extension method to the controller.
public static class ControllerExtensions
{
public static string GetURI(this Controller controller)
{
Uri location = new Uri($"{ controller.Request.Scheme}://{controller.Request.Host}");
string applicationRootURL = location.AbsoluteUri;
return applicationRootURL;
}
}
Once the extension method is written you can call it in the following manner.
public IActionResult Index()
{
var url = this.GetURI();
return View();
}
Make sure to import namespace of an extension method in your calling code

Need Help Getting HTML out of Razor View in ASP.NET Core With Action Result Filter

I'm following Steve Smith's article on how to use Filters in ASP.NET Core. Specifically, I want to get the HTML after it has been processed by the razor view engine. I've created an action filter and decorated my controller as follows yet I still get an empty html string from the stream. I think it has something to do with using the Result and not the Context but I'm not sure. Here is my code:
[AppendToHtmlBodyFilter]
public IActionResult Videos()
{
return View();
}
public void OnResultExecuted(ResultExecutedContext context)
{
Stream originalStream = context.HttpContext.Response.Body;
using (MemoryStream newStream = new MemoryStream())
{
context.HttpContext.Response.Body = newStream;
context.HttpContext.Response.Body = originalStream;
newStream.Seek(0, SeekOrigin.Begin);
StreamReader reader = new StreamReader(newStream);
var htmlData = reader.ReadToEnd();
}

how to handle ActionResult in custome class?

i have a class (in project by mvc4 razor on .net 4.5) and want to handle a Redirecting method on it and do not want inherit from controller class.
how can i handle this?it returns ActionResult to redirecting user in some cases like log outing
my main class:
public class SecuritySrv
{
public ActionResult Redirect()
{
return RedirectToAction("Logout", "Account", new { area = "" });
}
}
and i want to use it in some controllers like below:
public ActionResult AccountHome()
{
SecuritySrv SecurityService =new SecuritySrv()
if(.....)
return SecurityService.Redirect();
return view();
}
You can use this code anywhere, and you don't need an UrlHelper or access to the context, so you don't need to inherit the Controller class.
RouteValueDictionary rvd = new RouteValueDictionary
{
{"controller", "Profile"},
{"action", "Users"},
{"area", ""}
};
return new RedirectToRouteResult(rvd);
The RedirectToAction method of controller is just a helper for creating RedirectToRouteResult, you can create it by yourself in your class:
public class SecuritySrv
{
public ActionResult Redirect()
{
RouteValueDictionary routeValues = new RouteValueDictionary();
routeValues["action"] = "Logout";
routeValues["controller"] = "Account";
routeValues["area"] = "";
return new RedirectToRouteResult(routeValues);
}
}
And call this method from your controller in the way you wanted to.