Read AssemblyTitle attribute in ASP.NET - asp.net

I use code below to read AssemblyTitle attribute of .NET apps, unfortunately Assembly.GetEntryAssembly() always return Null in ASP.NET app. How to read AssemblyTitle in ASP.NET app?
public static string Title
{
get
{
var attributes = Assembly.GetEntryAssembly().GetCustomAttributes(typeof(AssemblyTitleAttribute), false);
if (attributes.Length > 0)
{
var titleAttribute = (AssemblyTitleAttribute)attributes[0];
if (titleAttribute.Title.Length > 0)
return titleAttribute.Title;
}
return System.IO.Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().CodeBase);
}
}

You must have a type that you know is defined in the same assembly that contains the AssemblyTitle. Then you can do:
typeof(MyType).Assembly.GetCustomAttributes
Note that (for what I know) there isn't any other bulletproof method.
For example using HttpContext.Current doesn't work if you want to do it not during a web request (so you can do it on response of a user action, but not from a separate thread, or from a static initializer, or from global.asax)
Some similar readings (full of half successes):
GetEntryAssembly for web applications
Using the Web Application version number from an assembly (ASP.NET/C#)

I use the following in asp.net web app:
if (ApplicationDeployment.IsNetworkDeployed)
return ApplicationDeployment.CurrentDeployment.CurrentVersion.ToString();
return System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
Edit: Sorry, thats just the version, not the title! I combined your version and mine:
System.Reflection.Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyTitleAttribute), false);
That gets the assembly title attribute just fine. The difference is in GetExecutingAssembly() versus your GetEntryAssembly().

Related

Alternative to Server.Transfer in ASP.NET Core

I am migrating an ASP.NET application to ASP.NET Core and they have some calls to HttpServerUtility.Transfer(string path). However, HttpServerUtility does not exist in ASP.NET Core.
Is there an alternative that I can use? Or is Response.Redirect the only option I have?
I want to maintain the same behaviour as the old application as much as possible since there is a difference in between Server.Transfer and Response.Redirect.
I see some options for you, depending on your case:
Returning another View: So just the HTML. See answer of Muqeet Khan
Returning another method of the same controller: This allows also the execution of the business logic of the other action. Just write something like return MyOtherAction("foo", "bar").
Returning an action of another controller: See the answer of Ron C. I am a bit in troubles with this solution since it omits the whole middleware which contains like 90% of the logic of ASP.NET Core (like security, cookies, compression, ...).
Routing style middleware: Adding a middleware similar to what routing does. In this case your decision logic needs to be evaluated there.
Late re-running of the middleware stack: You essentially need to re-run a big part of the stack. I believe it is possible, but have not seen a solution yet. I have seen a presentation of Damian Edwards (PM for ASP.NET Core) where he hosted ASP.NET Core without Kestrel/TCPIP usage just for rendering HTML locally in a browser. That you could do. But that is a lot of overload.
A word of advice: Transfer is dead ;). Differences like that is the reason for ASP.NET Core existence and performance improvements. That is bad for migration but good for the overall platform.
You are correct. Server.Transfer and Server.Redirect are quite different. Server.Transfer executes a new page and returns it's results to the browser but does not inform the browser that it returned a different page. So in such a case the browser url will show the original url requested but the contents will come from some other page. This is quite different than doing a Server.Redirect which will instruct the browser to request the new page. In such a case the url displayed in the browser will change to show the new url.
To do the equivalent of a Server.Transfer in Asp.Net Core, you need to update the Request.Path and Request.QueryString properties to point to the url you want to transfer to and you need to instantiate the controller that handles that url and call it's action method. I have provided full code below to illustrate this.
page1.html
<html>
<body>
<h1>Page 1</h1>
</body>
</html>
page2.html
<html>
<body>
<h1>Page 2</h1>
</body>
</html>
ExampleTransferController.cs
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace App.Web.Controllers {
public class ExampleTransferController: Controller {
public ExampleTransferController() {
}
[Route("/example-transfer/page1")]
public IActionResult Page1() {
bool condition = true;
if(condition) {
//Store the original url in the HttpContext items
//so that it's available to the app.
string originalUrl = $"{HttpContext.Request.Scheme}://{HttpContext.Request.Host}{HttpContext.Request.Path}{HttpContext.Request.QueryString}";
HttpContext.Items.Add("OriginalUrl", originalUrl);
//Modify the request to indicate the url we want to transfer to
string newPath = "/example-transfer/page2";
string newQueryString = "";
HttpContext.Request.Path = newPath;
HttpContext.Request.QueryString = new QueryString(newQueryString);
//Now call the action method for that new url
//Note that instantiating the controller for the new action method
//isn't necessary if the action method is on the same controller as
//the action method for the original request but
//I do it here just for illustration since often the action method you
//may want to call will be on a different controller.
var controller = new ExampleTransferController();
controller.ControllerContext = new ControllerContext(this.ControllerContext);
return controller.Page2();
}
return View();
}
[Route("/example-transfer/page2")]
public IActionResult Page2() {
string originalUrl = HttpContext.Items["OriginalUrl"] as string;
bool requestWasTransfered = (originalUrl != null);
return View();
}
}
}
Placing the original url in HttpContext.Items["OriginalUrl"] isn't strictly necessary but doing so makes it easy for the end page to know if it's responding to a transfer and if so what the original url was.
I can see this is a fairly old thread. I don't know when URL Rewriting was added to .Net Core but the answer is to rewrite the URL in the middleware, it's not a redirect, does not return to the server, does not change the url in the browser address bar, but does change the route.
resources:
https://weblog.west-wind.com/posts/2020/Mar/13/Back-to-Basics-Rewriting-a-URL-in-ASPNET-Core
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/url-rewriting?view=aspnetcore-5.0
I believe you are looking for a "named view" return in MVC. Like so,
[HttpPost]
public ActionResult Index(string Name)
{
ViewBag.Message = "Some message";
//Like Server.Transfer() in Asp.Net WebForm
return View("MyIndex");
}
The above will return that particular view. If you have a condition that governs the view details you can do that too.
I know that this is a very old question, but if someone uses Razor Pages and is looking to a Server.Transfer alternative (or a way to return a different view depending on a business rule), you can use partial views.
In this example, my viewmodel has a property called "UseAlternateView":
public class TestModel : PageModel
{
public bool UseAlternateView { get; set; }
public void OnGet()
{
// Here goes code that can set UseAlternateView=true in certain conditions
}
}
In my Razor View, I renderize a diferent partial view depending of the value of the UseAlternateView property:
#model MyProject.Pages.TestModel
#if (Model.UseAlternateView)
{
await Html.RenderPartialAsync("_View1", Model);
}
else
{
await Html.RenderPartialAsync("_View2", Model);
}
The partial views (files "_View1.cshtml" and "_View2.cshtml"), contain code like this:
#model MyProject.Pages.TestModel
<div>
Here goes page content, including forms with binding to Model properties
when necessary
</div>
Obs.: when using partial views like this, you cannot use #Region, so you may need to look for an anternative for inserting scripts and styles in the correct place on the master page.

When adding Web Reference for WCF to ASP.NET 2.0 there are two additional parameters added

I have developed a WCF in ASP.NET 4.5 with a couple of simple methods. One such method has a return type of bool (written in c#). When I add this service to my ASP.NET 4.5 web application as a Service Reference, it works as expected in the code behind. It also works the same way in a .NET 4.5 C# Console application. Below is the code in the Implementation file for this method:
public bool AddADUser(string a, string b)
{
bool done = false;
return done;
}
When I call it from my programs, it looks like this:
static void Main(string[] args)
{
var proxy = new ServiceReference1.ADServiceClient();
proxy.Open();
try
{
Console.WriteLine(proxy.HelloWorld());
bool success = proxy.AddADUser("testA", "testB");
Console.WriteLine(success.ToString());
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.InnerException);
}
finally
{
proxy.Close();
}
}
This is how it works in my ASP.NET 4.5 / C# app, and my C# .NET 4.5 Console App.
When I add this as a "Web Reference" to an existing ASP.NET 2.0 / VB.NET app, it does something different. The command to call the AddADUser() function is all of a sudden requiring 4 parameters:
AddADUser(a As String, b As String, ByRef AddADUserResult As Boolean, ByRef AddADUserResultSpecified As Boolean)
Why are these parameters being added -- is this something with VB.NET not allowing this to actually return a boolean, or a web reference not being able to return a boolean, or a problem with this being ASP.NET 2.0 ?
Or do I need to make a custom DataContract? I have that part left out of my Interface, just relying on defaults. Do I need to specify XmlSerializer somewhere also to be able to use this? It appears to actually do what it is supposed to, and I just can't figure out why there are two booleans and which one is the one I want.
This page gives a long explanation about it and a weird workaround that I didn't feel like doing:
http://www.codeproject.com/Articles/323097/WCF-ASMX-Interoperability-Removing-the-Annoying-xx
What I wound up doing was adding
[OperationContract, XmlSerializerFormat(Style = OperationFormatStyle.Rpc)]
to my methods and I also added
[ServiceContract,XmlSerializerFormat]
to my interface attribute and now they act like I would expect.
Reference: http://www.wenda.io/questions/1191041/result-and-resultspecified-parameters-in-wcf-service.html

Is it thread-safe to write this?

Can I write something like the following (in an assembly being used in an ASP.NET web page)?
public static string CurrentAuthenticatedUserFromHttpRequest
{
get
{
if (HttpContext.Current.Items["AuthUser"] == null)
{
return string.Empty;
}
return HttpContext.Current.Items["AuthUser"].ToString(); //set in "TryAuthenticate"
}
}
It is going to be a static read-only property. The value (to HttpContext.Current.Items["AuthUser"]) is set through a httphandler.
Just wondering on how this would perform during multiple requests. Is the data going to be accurate when multiple users try to access the same property (in multiple requests), even when high volumes of requests come in?
Yes, this is threadsafe. The static HttpContext.Current property differs per thread and contains the context for the request that the thread is currently handling.

Session variable are set to null between page

I have a solution with 2 projects : Core and Web. In the Core, I manage session I do something and I call this method :
public void SetLog()
{
HttpContext.Current.Session["Logged"] = true;
}
That's work.
When I change page (I use the ASP.NET 4.0 default template for testing), I click on the "About" link and I call this method :
public bool IsLogged()
{
if (HttpContext.Current.Session["Logged"] == null)
return false;
return true;
}
On the About page, Session are null, normal ? how solve this ?
Thanks,
I suspect that you have 2 web applications: Core and Web hosted on 2 different domains: http://localhost:1234 and http://localhost:5678. You seem to be setting the session variable inside the first web application but this session is only about the first application. As soon as you leave this application the other has a completely distinct session. Remember that sessions cannot be shared between ASP.NET applications. There are workarounds for this but out of the box it doesn't work.

How to get consistent AJAX response in all .NET Frameworks?

As of ASP.NET 3.5, all AJAX responses from ASP.NET Web Services are enclosed inside a d object.
This is the case with all ASMX services JSON serialized through the
ASP.NET AJAX Extensions in ASP.NET 3.5. Even if you’re only returning
a scalar return value, such as a string, int, or boolean, the result
will always be enclosed within the “d”.
http://encosia.com/a-breaking-change-between-versions-of-aspnet-ajax/
Therefore with pre-3.5 applications you'd do the following:
success(data)
{
var value = data;
}
With 3.5+ you must do:
success(data)
{
var value = data.d;
}
I've got an application which is ran on post-3.5 and pre-3.5.
How can I keep my code consistent for these applications?
Also this would be useful so that I don't have to change the code in the pre-3.5 applications when they are upgraded.
you could have a little helper function:
function GiveMeMyDamnData(data){
if(data.d)
return data.d;
return data;
}
then...
success(data)
{
var value = GiveMeMyDamnData(data);
}
...just need to make sure you never use a 'd' property in the AJAX response (else that will get confusing!

Resources